Coverage for /Syzygy/pe/coff_file.cc

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

Coverage information generated Thu Jan 14 17:40:38 2016.