Coverage for /Syzygy/pe/pe_coff_file_impl.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
85.4%1401640.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    :  // Template implementation of common definitions and helper routines
  16    :  // for reading both PE and COFF file formats.
  17    :  
  18    :  #ifndef SYZYGY_PE_PE_COFF_FILE_IMPL_H_
  19    :  #define SYZYGY_PE_PE_COFF_FILE_IMPL_H_
  20    :  
  21    :  namespace pe {
  22    :  
  23    :  template <typename AddressSpaceTraits>
  24  E :  void PECoffFile<AddressSpaceTraits>::Init(const base::FilePath& path) {
  25  E :    path_ = path;
  26  E :  }
  27    :  
  28    :  template <typename AddressSpaceTraits>
  29    :  bool PECoffFile<AddressSpaceTraits>::Contains(AddressType addr,
  30  E :                                                SizeType len) const {
  31  E :    const ImageAddressSpace::Range range(addr, len);
  32  E :    return image_data_.FindContaining(range) != image_data_.ranges().end();
  33  E :  }
  34    :  
  35    :  template <typename AddressSpaceTraits>
  36    :  size_t PECoffFile<AddressSpaceTraits>::GetSectionIndex(AddressType addr,
  37  E :                                                         SizeType len) const {
  38  E :    const ImageAddressSpace::Range range(addr, len);
  39    :    ImageAddressSpace::RangeMap::const_iterator it =
  40  E :        image_data_.FindContaining(range);
  41  E :    if (it == image_data_.ranges().end())
  42  E :      return kInvalidSection;
  43  E :    return it->second.id;
  44  E :  }
  45    :  
  46    :  template <typename AddressSpaceTraits>
  47    :  const IMAGE_SECTION_HEADER* PECoffFile<AddressSpaceTraits>::GetSectionHeader(
  48  E :      AddressType addr, SizeType len) const {
  49  E :    size_t id = GetSectionIndex(addr, len);
  50  E :    if (id == kInvalidSection)
  51  E :      return NULL;
  52  E :    DCHECK_LT(id, file_header_->NumberOfSections);
  53  E :    return section_headers_ + id;
  54  E :  }
  55    :  
  56    :  template <typename AddressSpaceTraits>
  57    :  std::string PECoffFile<AddressSpaceTraits>::GetSectionName(
  58  E :      const IMAGE_SECTION_HEADER& section) {
  59  E :    const char* name = reinterpret_cast<const char*>(section.Name);
  60  E :    return std::string(name, strnlen(name, arraysize(section.Name)));
  61  E :  }
  62    :  
  63    :  template <typename AddressSpaceTraits>
  64    :  std::string PECoffFile<AddressSpaceTraits>::GetSectionName(
  65  E :      size_t section_index) const {
  66  E :    DCHECK_LT(section_index, file_header_->NumberOfSections);
  67    :  
  68  E :    const IMAGE_SECTION_HEADER* section = section_headers_ + section_index;
  69  E :    return GetSectionName(*section);
  70  E :  }
  71    :  
  72    :  template <typename AddressSpaceTraits>
  73    :  bool PECoffFile<AddressSpaceTraits>::ReadCommonHeaders(
  74  E :      FILE* file, FileOffsetAddress file_header_start) {
  75    :    // Test for unsupported object files.
  76    :    uint16 obj_sig[2];
  77  E :    if (!ReadAt(file, 0, obj_sig, sizeof(obj_sig))) {
  78  i :      LOG(ERROR) << "Unable to read first 4 bytes from object file.";
  79  i :      return false;
  80    :    }
  81  E :    if (obj_sig[0] == 0 && obj_sig[1] == 0xFFFF) {
  82  E :      LOG(ERROR) << "Unsupported anonymous object file.";
  83  E :      return false;
  84    :    }
  85    :  
  86    :    // Read the COFF file header.
  87  E :    IMAGE_FILE_HEADER file_header = {};
  88    :    if (!ReadAt(file, file_header_start.value(),
  89  E :                &file_header, sizeof(file_header))) {
  90  i :      LOG(ERROR) << "Unable to read COFF file header.";
  91  i :      return false;
  92    :    }
  93    :  
  94    :    // Compute size of all headers, from the beginning of the file to
  95    :    // the end of the section table.
  96    :    FileOffsetAddress opt_header_start(file_header_start.value() +
  97  E :                                       sizeof(file_header));
  98    :    FileOffsetAddress section_table_start(opt_header_start +
  99  E :                                          file_header.SizeOfOptionalHeader);
 100    :    SizeType section_table_size(
 101  E :        file_header.NumberOfSections * sizeof(IMAGE_SECTION_HEADER));
 102  E :    FileOffsetAddress header_end(section_table_start + section_table_size);
 103  E :    SizeType header_size = header_end.value();
 104  E :    if (file_header.SizeOfOptionalHeader != 0) {
 105  E :      IMAGE_OPTIONAL_HEADER opt_header = {};
 106    :      if (!ReadAt(file, opt_header_start.value(),
 107  E :                  &opt_header, sizeof(opt_header))) {
 108  i :        LOG(ERROR) << "Unable to read optional header.";
 109  i :        return false;
 110    :      }
 111    :      // In a sane world the stated header size will match that manually
 112    :      // calculated by walking the headers and aligning up by the file alignment.
 113    :      // However, this is not necessary for the PE file to be valid, and there may
 114    :      // be a gap between the two.
 115  E :      header_size = opt_header.SizeOfHeaders;
 116    :    }
 117    :  
 118    :    // We now know how large the headers are, so create a range for them.
 119  E :    ImageAddressSpace::Range header_range(header_address(), header_size);
 120    :    if (!InsertRangeReadAt(file, FileOffsetAddress(0), header_size,
 121  E :                           header_range)) {
 122  i :      return false;
 123    :    }
 124    :  
 125    :    bool success = GetImageData(header_address() + file_header_start.value(),
 126    :                                SizeType(sizeof(*file_header_)),
 127  E :                                &file_header_);
 128  E :    DCHECK(success);
 129    :    success = GetImageData(header_address() + section_table_start.value(),
 130    :                           section_table_size,
 131  E :                           &section_headers_);
 132  E :    DCHECK(success);
 133    :  
 134  E :    return success;
 135  E :  }
 136    :  
 137    :  template <typename AddressSpaceTraits>
 138  E :  bool PECoffFile<AddressSpaceTraits>::ReadSections(FILE* file) {
 139  E :    DCHECK(file_header_ != NULL);
 140  E :    DCHECK(section_headers_ != NULL);
 141    :  
 142  E :    size_t num_sections = file_header_->NumberOfSections;
 143  E :    for (size_t i = 0; i < num_sections; ++i) {
 144  E :      const IMAGE_SECTION_HEADER* hdr = section_headers_ + i;
 145    :  
 146    :      // Construct address in the new address space; FromSectionHeader()
 147    :      // returns header_address() if unmapped.
 148  E :      AddressType addr = AddressSpaceTraits::GetSectionAddress(*hdr);
 149    :  
 150    :      // Ignore unmapped sections, as those, by definition, have no
 151    :      // address to map to within our address space. They need to be
 152    :      // handled separately during decomposition.
 153  E :      if (addr == AddressSpaceTraits::invalid_address())
 154  E :        continue;
 155    :  
 156    :      // Empty sections are ignored at this level of the parsing.
 157  E :      size_t section_size = AddressSpaceTraits::GetSectionSize(*hdr);
 158  E :      if (section_size == 0)
 159  i :        continue;
 160    :  
 161    :      // Insert the range for the new section.
 162  E :      ImageAddressSpace::Range section_range(addr, section_size);
 163  E :      ImageAddressSpace::RangeMap::iterator it;
 164  E :      if (!image_data_.Insert(section_range, SectionInfo(), &it)) {
 165  i :        LOG(ERROR) << "Unable to insert range for section " << hdr->Name << ".";
 166  i :        return false;
 167    :      }
 168    :  
 169  E :      it->second.id = i;
 170  E :      SectionBuffer& buf = it->second.buffer;
 171  E :      if (hdr->SizeOfRawData == 0)
 172  i :        continue;
 173    :  
 174  E :      buf.resize(hdr->SizeOfRawData);
 175  E :      if (!ReadAt(file, hdr->PointerToRawData, &buf.at(0), hdr->SizeOfRawData)) {
 176  i :        LOG(ERROR) << "Unable to read data for section " << hdr->Name << ".";
 177  i :        return false;
 178    :      }
 179  E :    }
 180    :  
 181  E :    return true;
 182  E :  }
 183    :  
 184    :  template <typename AddressSpaceTraits>
 185    :  bool PECoffFile<AddressSpaceTraits>::InsertRangeReadAt(
 186    :      FILE* file, FileOffsetAddress start, size_t size,
 187  E :      const typename ImageAddressSpace::Range& range) {
 188  E :    ImageAddressSpace::RangeMap::iterator it;
 189  E :    bool inserted = image_data_.Insert(range, SectionInfo(), &it);
 190  E :    if (!inserted) {
 191  i :      LOG(ERROR) << "Unable to create new range in address space.";
 192  i :      return false;
 193    :    }
 194    :  
 195  E :    SectionBuffer& buffer = it->second.buffer;
 196  E :    buffer.resize(size);
 197  E :    if (!ReadAt(file, start.value(), &buffer[0], size)) {
 198  i :      LOG(ERROR) << "Unable to file data.";
 199  i :      return false;
 200    :    }
 201    :  
 202  E :    return true;
 203  E :  }
 204    :  
 205    :  template <typename AddressSpaceTraits>
 206    :  bool PECoffFile<AddressSpaceTraits>::ReadAt(FILE* file, size_t pos,
 207  E :                                              void* buf, size_t len) {
 208  E :    if (fseek(file, pos, SEEK_SET) != 0)
 209  i :      return false;
 210    :  
 211  E :    size_t read = fread(buf, 1, len, file);
 212  E :    if (read != len)
 213  i :      return false;
 214    :  
 215  E :    return true;
 216  E :  }
 217    :  
 218    :  template <typename AddressSpaceTraits>
 219    :  const uint8* PECoffFile<AddressSpaceTraits>::GetImageData(AddressType addr,
 220  E :                                                            SizeType len) const {
 221  E :    ImageAddressSpace::Range range(addr, len);
 222    :    ImageAddressSpace::RangeMap::const_iterator it(
 223  E :        image_data_.FindContaining(range));
 224    :  
 225  E :    if (it != image_data_.ranges().end()) {
 226  E :      ptrdiff_t offs = addr - it->first.start();
 227  E :      DCHECK_GE(offs, 0);
 228    :  
 229  E :      const SectionBuffer& buf = it->second.buffer;
 230  E :      if (offs + len <= buf.size())
 231  E :        return &buf.at(offs);
 232    :    }
 233    :  
 234  E :    return NULL;
 235  E :  }
 236    :  
 237    :  template <typename AddressSpaceTraits>
 238    :  uint8* PECoffFile<AddressSpaceTraits>::GetImageData(AddressType addr,
 239  E :                                                      SizeType len) {
 240    :    return const_cast<uint8*>(
 241  E :        static_cast<const PECoffFile*>(this)->GetImageData(addr, len));
 242  E :  }
 243    :  
 244    :  template <typename AddressSpaceTraits>
 245    :  template <typename ItemType>
 246    :  bool PECoffFile<AddressSpaceTraits>::GetImageData(
 247  E :      AddressType addr, SizeType len, const ItemType** item_ptr) const {
 248  E :    const uint8* ptr = GetImageData(addr, len);
 249  E :    if (ptr == NULL)
 250  i :      return false;
 251  E :    *item_ptr = reinterpret_cast<const ItemType*>(ptr);
 252  E :    return true;
 253  E :  }
 254    :  
 255    :  template <typename AddressSpaceTraits>
 256    :  template <typename ItemType>
 257    :  bool PECoffFile<AddressSpaceTraits>::GetImageData(
 258  E :      AddressType addr, SizeType len, ItemType** item_ptr) {
 259  E :    uint8* ptr = GetImageData(addr, len);
 260  E :    if (ptr == NULL)
 261  i :      return false;
 262  E :    *item_ptr = reinterpret_cast<ItemType*>(ptr);
 263  E :    return true;
 264  E :  }
 265    :  
 266    :  template <typename AddressSpaceTraits>
 267    :  bool PECoffFile<AddressSpaceTraits>::ReadImage(AddressType addr,
 268  E :                                                 void* data, SizeType len) const {
 269  E :    DCHECK(data != NULL);
 270  E :    const uint8* buf = GetImageData(addr, len);
 271  E :    if (buf == NULL)
 272  i :      return false;
 273    :  
 274  E :    memcpy(data, buf, len);
 275  E :    return true;
 276  E :  }
 277    :  
 278    :  template <typename AddressSpaceTraits>
 279    :  bool PECoffFile<AddressSpaceTraits>::ReadImageString(AddressType addr,
 280  E :                                                       std::string* str) const {
 281  E :    DCHECK(file_header_ != NULL);
 282  E :    str->clear();
 283    :  
 284    :    // Locate the range that contains the first byte of the string.
 285  E :    ImageAddressSpace::Range range(addr, 1);
 286    :    ImageAddressSpace::RangeMap::const_iterator it(
 287  E :        image_data_.FindContaining(range));
 288    :  
 289  E :    if (it != image_data_.ranges().end()) {
 290  E :      ptrdiff_t offs = addr - it->first.start();
 291  E :      DCHECK_GE(offs, 0);
 292    :      // Stash the start position.
 293  E :      const SectionBuffer& buf = it->second.buffer;
 294  E :      const char* begin = reinterpret_cast<const char*>(&buf.at(offs));
 295    :      // And loop through until we find a zero-terminating byte,
 296    :      // or run off the end.
 297  E :      for (; static_cast<size_t>(offs) < buf.size() && buf.at(offs); ++offs) {
 298    :        // Intentionally empty.
 299  E :      }
 300    :  
 301  E :      if (static_cast<size_t>(offs) == buf.size())
 302  i :        return false;
 303    :  
 304  E :      str->assign(begin);
 305  E :      return true;
 306    :    }
 307    :  
 308  i :    return false;
 309  E :  }
 310    :  
 311    :  }  // namespace  pe
 312    :  
 313    :  #endif  // SYZYGY_PE_PE_COFF_FILE_IMPL_H_

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