Coverage for /Syzygy/pe/coff_file.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
83.7%1031230.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    :  #include "syzygy/pe/coff_file.h"
  16    :  
  17    :  #include "base/file_util.h"
  18    :  #include "base/logging.h"
  19    :  
  20    :  namespace pe {
  21    :  
  22    :  using core::FileOffsetAddress;
  23    :  
  24    :  CoffFile::CoffFile()
  25    :      : symbols_(NULL),
  26    :        strings_(NULL),
  27    :        symbols_offset_(),
  28    :        symbols_size_(0),
  29    :        strings_offset_(),
  30    :        strings_size_(0),
  31  E :        reloc_infos_() {
  32  E :  }
  33    :  
  34  E :  CoffFile::~CoffFile() {
  35  E :  }
  36    :  
  37  E :  bool CoffFile::Init(const base::FilePath& path) {
  38  E :    PECoffFile::Init(path);
  39    :  
  40  E :    base::ScopedFILE file(base::OpenFile(path, "rb"));
  41  E :    if (file.get() == NULL) {
  42  i :      LOG(ERROR) << "Failed to open file " << path.value() << ".";
  43  i :      return false;
  44    :    }
  45    :  
  46  E :    bool success = ReadCommonHeaders(file.get(), FileOffsetAddress(0));
  47  E :    if (success)
  48  E :      success = ReadSections(file.get());
  49  E :    if (success)
  50  E :      success = ReadNonSections(file.get());
  51    :  
  52  E :    return success;
  53  E :  }
  54    :  
  55    :  bool CoffFile::FileOffsetToSectionOffset(FileOffsetAddress addr,
  56    :                                           size_t* section_index,
  57  E :                                           size_t* offset) const {
  58  E :    DCHECK(section_index != NULL);
  59  E :    DCHECK(offset != NULL);
  60    :  
  61    :    ImageAddressSpace::RangeMap::const_iterator it =
  62  E :        image_data_.FindContaining(ImageAddressSpace::Range(addr, 1));
  63  E :    if (it == image_data_.ranges().end())
  64  i :      return false;
  65  E :    if (it->second.id == kInvalidSection || addr >= it->first.end())
  66  i :      return false;
  67    :  
  68  E :    *section_index = it->second.id;
  69  E :    *offset = addr - it->first.start();
  70  E :    return true;
  71  E :  }
  72    :  
  73    :  bool CoffFile::SectionOffsetToFileOffset(size_t section_index,
  74    :                                           size_t offset,
  75  E :                                           FileOffsetAddress* addr) const {
  76  E :    DCHECK(addr != NULL);
  77    :  
  78  E :    if (section_index >= file_header_->NumberOfSections) {
  79  i :      LOG(ERROR) << "Unknown section index " << section_index << ".";
  80  i :      return false;
  81    :    }
  82    :  
  83  E :    const IMAGE_SECTION_HEADER* header = &section_headers_[section_index];
  84  E :    if (offset > header->SizeOfRawData) {
  85  i :      LOG(ERROR) << "Section offset " << section_index << " out of bounds.";
  86  i :      return false;
  87    :    }
  88    :  
  89  E :    addr->set_value(header->PointerToRawData + offset);
  90  E :    return true;
  91  E :  }
  92    :  
  93  E :  bool CoffFile::ReadNonSections(FILE* file) {
  94  E :    DCHECK(file != NULL);
  95  E :    DCHECK(file_header_ != NULL);
  96    :  
  97    :    // Map the symbol table into our address space.
  98  E :    FileOffsetAddress symbols_start(file_header_->PointerToSymbolTable);
  99  E :    size_t symbols_size = file_header_->NumberOfSymbols * sizeof(*symbols_);
 100  E :    ImageAddressSpace::Range symbols_range(symbols_start, symbols_size);
 101  E :    if (!InsertRangeReadAt(file, symbols_start, symbols_size, symbols_range))
 102  i :      return false;
 103    :  
 104    :    // Get the pointer to our internal data range.
 105  E :    CHECK(GetImageData(symbols_start, symbols_size, &symbols_));
 106  E :    symbols_offset_ = symbols_start;
 107  E :    symbols_size_ = symbols_size;
 108    :  
 109    :    // Map the string table into our address space.
 110  E :    FileOffsetAddress strings_start(symbols_start + symbols_size);
 111  E :    uint32 strings_size = 0;
 112    :    if (!ReadAt(file, strings_start.value(),
 113  E :                &strings_size, sizeof(strings_size))) {
 114  i :      LOG(ERROR) << "Unable to read string table size.";
 115  i :      return false;
 116    :    }
 117  E :    if (strings_size > 0) {
 118  E :      ImageAddressSpace::Range strings_range(strings_start, strings_size);
 119  E :      if (!InsertRangeReadAt(file, strings_start, strings_size, strings_range))
 120  i :        return false;
 121    :  
 122  E :      CHECK(GetImageData(strings_start, strings_size, &strings_));
 123    :    }
 124  E :    strings_offset_ = strings_start;
 125  E :    strings_size_ = strings_size;
 126    :  
 127    :    // Map relocation data for every section.
 128  E :    size_t num_sections = file_header_->NumberOfSections;
 129  E :    reloc_infos_.resize(num_sections);
 130  E :    for (size_t i = 0; i < num_sections; ++i) {
 131  E :      const IMAGE_SECTION_HEADER* header = section_header(i);
 132  E :      FileOffsetAddress relocs_start(header->PointerToRelocations);
 133    :  
 134  E :      size_t num_relocs = header->NumberOfRelocations;
 135  E :      if ((header->Characteristics & IMAGE_SCN_LNK_NRELOC_OVFL) != 0) {
 136  i :        DCHECK_EQ(num_relocs, 0xffffu);
 137    :        IMAGE_RELOCATION reloc;
 138    :        if (!ReadAt(file, header->PointerToRelocations,
 139  i :                    &reloc, sizeof(reloc))) {
 140  i :          LOG(ERROR) << "Unable to read extended relocation count.";
 141  i :          return false;
 142    :        }
 143  i :        num_relocs = reloc.VirtualAddress;
 144    :      }
 145    :  
 146  E :      if (num_relocs == 0)
 147  E :        continue;
 148  E :      size_t relocs_size = num_relocs * sizeof(IMAGE_RELOCATION);
 149    :  
 150  E :      ImageAddressSpace::Range relocs_range(relocs_start, relocs_size);
 151  E :      if (!InsertRangeReadAt(file, relocs_start, relocs_size, relocs_range))
 152  i :        return false;
 153    :  
 154    :      // Save section relocation info to avoid recomputing pointer and
 155    :      // size from headers.
 156  E :      CHECK(GetImageData(relocs_start, relocs_size, &reloc_infos_[i].relocs_));
 157  E :      reloc_infos_[i].num_relocs_ = num_relocs;
 158  E :    }
 159    :  
 160  E :    return true;
 161  E :  }
 162    :  
 163  E :  void CoffFile::DecodeRelocs(RelocMap* reloc_map) const {
 164  E :    DCHECK(file_header_ != NULL);
 165  E :    DCHECK(symbols_ != NULL);
 166    :  
 167  E :    size_t num_sections = file_header_->NumberOfSections;
 168  E :    for (size_t i = 0; i < num_sections; ++i) {
 169  E :      CHECK(DecodeSectionRelocs(i, reloc_map));
 170  E :    }
 171  E :  }
 172    :  
 173    :  bool CoffFile::DecodeSectionRelocs(size_t section_index,
 174  E :                                     RelocMap* reloc_map) const {
 175  E :    DCHECK(file_header_ != NULL);
 176  E :    DCHECK(symbols_ != NULL);
 177    :  
 178  E :    const IMAGE_SECTION_HEADER* header = section_header(section_index);
 179  E :    if (header == NULL)
 180  i :      return false;
 181    :  
 182  E :    IMAGE_RELOCATION* relocs = reloc_infos_[section_index].relocs_;
 183  E :    size_t num_relocs = reloc_infos_[section_index].num_relocs_;
 184    :  
 185  E :    for (size_t i = 0; i < num_relocs; ++i) {
 186  E :      size_t offset = relocs[i].VirtualAddress - header->VirtualAddress;
 187  E :      FileOffsetAddress addr(header->PointerToRawData + offset);
 188  E :      reloc_map->insert(std::make_pair(addr, &relocs[i]));
 189  E :    }
 190    :  
 191  E :    return true;
 192  E :  }
 193    :  
 194  E :  bool CoffFile::IsSectionMapped(size_t section_index) const {
 195  E :    DCHECK(section_headers_ != NULL);
 196    :  
 197  E :    const IMAGE_SECTION_HEADER* header = section_header(section_index);
 198    :    return header != NULL &&
 199    :        (CoffAddressSpaceTraits::GetSectionAddress(*header) !=
 200  E :         CoffAddressSpaceTraits::invalid_address());
 201  E :  }
 202    :  
 203  E :  const char* CoffFile::GetSymbolName(size_t symbol_index) const {
 204  E :    DCHECK(symbols_ != NULL);
 205    :  
 206  E :    IMAGE_SYMBOL* symbol = &symbols_[symbol_index];
 207  E :    if (symbol->N.Name.Short != 0)
 208  E :      return reinterpret_cast<const char*>(&symbol->N.ShortName);
 209  i :    else
 210  E :      return string(symbol->N.Name.Long);
 211  E :  }
 212    :  
 213    :  }  // namespace pe

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