Coverage for /Syzygy/agent/common/process_utils.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
60.9%39640.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    :  #include "syzygy/agent/common/process_utils.h"
  16    :  
  17    :  #include <psapi.h>
  18    :  
  19    :  #include "base/logging.h"
  20    :  #include "base/win/pe_image.h"
  21    :  #include "syzygy/common/com_utils.h"
  22    :  #include "syzygy/common/path_util.h"
  23    :  #include "syzygy/trace/client/rpc_session.h"
  24    :  
  25    :  namespace agent {
  26    :  namespace common {
  27    :  
  28    :  namespace {
  29    :  
  30    :  // Accessing a module acquired from process iteration calls is inherently racy,
  31    :  // as we don't hold any kind of reference to the module, and so the module
  32    :  // could be unloaded while we're accessing it.
  33    :  bool CaptureModuleInformation(const base::win::PEImage& image,
  34    :                                size_t* module_base_size,
  35    :                                uint32* module_checksum,
  36  i :                                uint32* module_time_date_stamp) {
  37  i :    DCHECK(module_base_size != NULL);
  38  i :    DCHECK(module_checksum != NULL);
  39  i :    DCHECK(module_time_date_stamp != NULL);
  40    :  
  41  i :    __try {
  42  i :      const IMAGE_NT_HEADERS* nt_headers = image.GetNTHeaders();
  43  i :      *module_base_size = nt_headers->OptionalHeader.SizeOfImage;
  44  i :      *module_checksum = nt_headers->OptionalHeader.CheckSum;
  45  i :      *module_time_date_stamp = nt_headers->FileHeader.TimeDateStamp;
  46    :  
  47    :      // Make reasonably sure we're actually looking at a module.
  48  i :      if (!image.VerifyMagic())
  49  i :        return false;
  50  i :    } __except(EXCEPTION_EXECUTE_HANDLER) {
  51  i :      return false;
  52  i :    }
  53    :  
  54  i :    return true;
  55  i :  }
  56    :  
  57    :  }  // namespace
  58    :  
  59  E :  void GetProcessModules(ModuleVector* modules) {
  60  E :    DCHECK(modules != NULL);
  61    :  
  62  E :    modules->resize(128);
  63  E :    while (true) {
  64  E :      DWORD bytes = sizeof(modules->at(0)) * modules->size();
  65  E :      DWORD needed_bytes = 0;
  66    :      BOOL success = ::EnumProcessModules(::GetCurrentProcess(),
  67    :                                          &modules->at(0),
  68    :                                          bytes,
  69  E :                                          &needed_bytes);
  70  E :      if (success && bytes >= needed_bytes) {
  71    :        // Success - break out of the loop.
  72    :        // Resize our module vector to the returned size.
  73  E :        modules->resize(needed_bytes / sizeof(modules->at(0)));
  74  E :        return;
  75    :      }
  76    :  
  77    :      // Resize our module vector with the needed size and little slop.
  78  i :      modules->resize(needed_bytes / sizeof(modules->at(0)) + 4);
  79  i :    }
  80  E :  }
  81    :  
  82    :  bool LogModule(HMODULE module,
  83    :                 trace::client::RpcSession* session,
  84  E :                 trace::client::TraceFileSegment* segment) {
  85  E :    DCHECK(module != NULL);
  86  E :    DCHECK(session != NULL);
  87  E :    DCHECK(segment != NULL);
  88    :  
  89    :    // See whether we can acquire the module data.
  90  E :    base::win::PEImage image(module);
  91  E :    size_t module_base_size = 0;
  92  E :    uint32 module_checksum = 0;
  93  E :    uint32 module_time_date_stamp = 0;
  94    :    if (!CaptureModuleInformation(image,
  95    :                                  &module_base_size,
  96    :                                  &module_checksum,
  97  E :                                  &module_time_date_stamp)) {
  98  E :      LOG(ERROR) << "Failed to capture module information.";
  99  E :      return false;
 100    :    }
 101    :  
 102    :    // Make sure the event we're about to write will fit.
 103    :    if (!segment->CanAllocate(sizeof(TraceModuleData)) ||
 104  E :        !session->ExchangeBuffer(segment)) {
 105    :      // Failed to allocate a new segment.
 106  i :      LOG(ERROR) << "Failed to exchange buffer.";
 107  i :      return false;
 108    :    }
 109    :  
 110  E :    DCHECK(segment->CanAllocate(sizeof(TraceModuleData)));
 111    :  
 112    :    // Allocate a record in the log.
 113    :    TraceModuleData* module_event = reinterpret_cast<TraceModuleData*>(
 114    :        segment->AllocateTraceRecordImpl(
 115  E :            TRACE_PROCESS_ATTACH_EVENT, sizeof(TraceModuleData)));
 116  E :    DCHECK(module_event != NULL);
 117    :  
 118  E :    module_event->module_base_addr = module;
 119  E :    module_event->module_base_size = module_base_size;
 120  E :    module_event->module_checksum = module_checksum;
 121  E :    module_event->module_time_date_stamp = module_time_date_stamp;
 122    :  
 123  E :    wchar_t module_name[MAX_PATH] = { 0 };
 124    :    if (::GetMappedFileName(::GetCurrentProcess(), module,
 125  E :                            module_name, arraysize(module_name)) == 0) {
 126  i :      DWORD error = ::GetLastError();
 127  i :      LOG(ERROR) << "Failed to get module name: " << ::common::LogWe(error)
 128    :                 << ".";
 129  i :      return false;
 130    :    }
 131  E :    base::FilePath device_path(module_name);
 132  E :    base::FilePath drive_path;
 133  E :    if (!::common::ConvertDevicePathToDrivePath(device_path, &drive_path)) {
 134  i :      LOG(ERROR) << "ConvertDevicePathToDrivePath failed.";
 135  i :      return false;
 136    :    }
 137    :    ::wcsncpy(module_event->module_name, drive_path.value().c_str(),
 138  E :              arraysize(module_event->module_name));
 139    :  
 140  E :    module_event->module_exe[0] = L'\0';
 141    :  
 142  E :    return true;
 143  E :  }
 144    :  
 145    :  }  // namespace common
 146    :  }  // namespace agent

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