Coverage for /Syzygy/trace/logger/logger_rpc_impl.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
75.0%811080.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    :  // This file implements the RPC stubs which bind the LoggerService RPC
  16    :  // handlers to a Logger instance.
  17    :  
  18    :  #include "syzygy/trace/logger/logger_rpc_impl.h"
  19    :  
  20    :  #include <windows.h>
  21    :  #include <winnt.h>
  22    :  
  23    :  #include "base/process.h"
  24    :  #include "base/win/scoped_handle.h"
  25    :  #include "sawbuck/common/com_utils.h"
  26    :  #include "syzygy/trace/logger/logger.h"
  27    :  #include "syzygy/trace/rpc/logger_rpc.h"
  28    :  
  29    :  namespace {
  30    :  
  31    :  using base::ProcessId;
  32    :  using base::win::ScopedHandle;
  33    :  using trace::logger::RpcLoggerInstanceManager;
  34    :  using trace::logger::Logger;
  35    :  
  36  E :  bool GetClientInfo(handle_t binding, ProcessId* pid, ScopedHandle* handle) {
  37  E :    DCHECK(pid != NULL);
  38  E :    DCHECK(handle != NULL);
  39    :  
  40    :    // Get the RPC call attributes.
  41    :    static const int kVersion = 2;
  42  E :    RPC_CALL_ATTRIBUTES_V2 attribs = { kVersion, RPC_QUERY_CLIENT_PID };
  43  E :    RPC_STATUS status = RpcServerInqCallAttributes(binding, &attribs);
  44  E :    if (status != RPC_S_OK) {
  45  i :      LOG(ERROR) << "Failed to query RPC call attributes: "
  46    :                 << com::LogWe(status) << ".";
  47  i :      return false;
  48    :    }
  49    :  
  50    :    // Extract the process id.
  51  E :    ProcessId the_pid = reinterpret_cast<ProcessId>(attribs.ClientPID);
  52    :  
  53    :    // Open and return the handle to the process.
  54    :    static const DWORD kFlags =
  55    :        PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
  56  E :    handle->Set(::OpenProcess(kFlags, FALSE, the_pid));
  57  E :    if (!handle->IsValid()) {
  58  i :      DWORD error = ::GetLastError();
  59  i :      LOG(ERROR) << "Failed to open PID=" << the_pid << ": " << com::LogWe(error)
  60    :                 << ".";
  61  i :      return false;
  62    :    }
  63    :  
  64    :    // And we're done.
  65  E :    *pid = the_pid;
  66  E :    return true;
  67  E :  }
  68    :  
  69  E :  void InitContext(const ExecutionContext* ext_ctx, CONTEXT* ctx) {
  70  E :    DCHECK(ext_ctx != NULL);
  71  E :    DCHECK(ctx != NULL);
  72    :  
  73  E :    ::memset(ctx, 0, sizeof(*ctx));
  74  E :    ctx->ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
  75    :  
  76    :    // Populate the integer registers.
  77  E :    ctx->Edi = ext_ctx->edi;
  78  E :    ctx->Esi = ext_ctx->esi;
  79  E :    ctx->Ebx = ext_ctx->ebx;
  80  E :    ctx->Edx = ext_ctx->edx;
  81  E :    ctx->Ecx = ext_ctx->ecx;
  82  E :    ctx->Eax = ext_ctx->eax;
  83    :  
  84    :    // Populate the control registers.
  85  E :    ctx->Ebp = ext_ctx->ebp;
  86  E :    ctx->Eip = ext_ctx->eip;
  87  E :    ctx->SegCs = ext_ctx->seg_cs;
  88  E :    ctx->EFlags = ext_ctx->eflags;
  89  E :    ctx->Esp = ext_ctx->esp;
  90  E :    ctx->SegSs = ext_ctx->seg_ss;
  91  E :  }
  92    :  
  93    :  }  // namespace
  94    :  
  95    :  // The instance to which the RPC callbacks are bound.
  96    :  Logger* RpcLoggerInstanceManager::instance_ = NULL;
  97    :  
  98    :  // RPC entrypoint for Logger::Write().
  99    :  boolean LoggerService_Write(
 100    :      /* [in] */ handle_t binding,
 101  E :      /* [string][in] */ const unsigned char *text) {
 102  E :    if (binding == NULL || text == NULL) {
 103  i :      LOG(ERROR) << "Invalid input parameter(s).";
 104  i :      return false;
 105    :    }
 106    :  
 107    :    // Get the logger instance.
 108  E :    Logger* instance = RpcLoggerInstanceManager::GetInstance();
 109    :  
 110    :    // Write the log message.
 111  E :    std::string message(reinterpret_cast<const char*>(text));
 112  E :    if (!instance->Write(message))
 113  i :      return false;
 114    :  
 115    :    // And we're done.
 116  E :    return true;
 117  E :  }
 118    :  
 119    :  boolean LoggerService_WriteWithContext(
 120    :      /* [in] */ handle_t binding,
 121    :      /* [in, string] */ const unsigned char* text,
 122  E :      /* [in */ const ExecutionContext* exc_context ) {
 123  E :    if (binding == NULL || text == NULL || exc_context == NULL) {
 124  i :      LOG(ERROR) << "Invalid input parameter(s).";
 125  i :      return false;
 126    :    }
 127    :  
 128    :    // Get the caller's process info.
 129  E :    ProcessId pid = 0;
 130  E :    ScopedHandle handle;
 131  E :    if (!GetClientInfo(binding, &pid, &handle))
 132  i :      return false;
 133    :  
 134    :    // Get the logger instance.
 135  E :    Logger* instance = RpcLoggerInstanceManager::GetInstance();
 136    :  
 137    :    // Capture the stack trace for the caller's context.
 138  E :    CONTEXT context = {};
 139  E :    InitContext(exc_context, &context);
 140  E :    std::vector<DWORD> trace_data;
 141  E :    if (!instance->CaptureRemoteTrace(handle, &context, &trace_data)) {
 142  i :      return false;
 143    :    }
 144    :  
 145    :    // Create the log message.
 146  E :    std::string message(reinterpret_cast<const char*>(text));
 147    :    if (!instance->AppendTrace(
 148  E :            handle, trace_data.data(), trace_data.size(), &message)) {
 149  i :      return false;
 150    :    }
 151    :  
 152    :    // Write the log message.
 153  E :    if (!instance->Write(message))
 154  i :      return false;
 155    :  
 156    :    // And we're done.
 157  E :    return true;
 158  E :  }
 159    :  
 160    :  boolean LoggerService_WriteWithTrace(
 161    :      /* [in] */ handle_t binding,
 162    :      /* [in, string] */ const unsigned char* text,
 163    :      /* [in, size_is(trace_length)] */ const unsigned long* trace_data,
 164  E :      /* [in] */ LONG trace_length) {
 165  E :    if (binding == NULL || text == NULL || trace_data == NULL) {
 166  i :      LOG(ERROR) << "Invalid input parameter(s).";
 167  i :      return false;
 168    :    }
 169    :  
 170    :    // Get the caller's process info.
 171  E :    ProcessId pid = 0;
 172  E :    ScopedHandle handle;
 173  E :    if (!GetClientInfo(binding, &pid, &handle))
 174  i :      return false;
 175    :  
 176    :    // Get the logger instance.
 177  E :    Logger* instance = RpcLoggerInstanceManager::GetInstance();
 178    :  
 179    :    // Create the log message.
 180  E :    std::string message(reinterpret_cast<const char*>(text));
 181  E :    if (!instance->AppendTrace(handle, trace_data, trace_length, &message))
 182  i :      return false;
 183    :  
 184    :    // Write the log message.
 185  E :    if (!instance->Write(message))
 186  i :      return false;
 187    :  
 188    :    // And we're done.
 189  E :    return true;
 190  E :  }
 191    :  
 192    :  // RPC entrypoint for Logger::SaveMinidump().
 193    :  boolean LoggerService_SaveMiniDump(
 194    :      /* [in] */ handle_t binding,
 195    :      /* [in] */ unsigned long thread_id,
 196    :      /* [in] */ unsigned long exception,
 197  E :      /* [in] */ unsigned long flags) {
 198  E :    if (binding == NULL) {
 199  i :      LOG(ERROR) << "Invalid input parameter(s).";
 200  i :      return false;
 201    :    }
 202    :  
 203    :    // Get the caller's process info.
 204  E :    ProcessId pid = 0;
 205  E :    ScopedHandle handle;
 206  E :    if (!GetClientInfo(binding, &pid, &handle))
 207  i :      return false;
 208    :  
 209  E :    Logger* instance = RpcLoggerInstanceManager::GetInstance();
 210  E :    if (!instance->SaveMiniDump(handle, pid, thread_id, exception, flags))
 211  i :      return false;
 212    :  
 213  E :    return true;
 214  E :  }
 215    :  
 216    :  // RPC entrypoint for Logger::Stop().
 217  E :  boolean LoggerService_Stop(/* [in] */ handle_t binding) {
 218  E :    if (binding == NULL) {
 219  i :      LOG(ERROR) << "Invalid input parameter(s).";
 220  i :      return false;
 221    :    }
 222    :  
 223    :    // Get the caller's process info.
 224  E :    ProcessId pid = 0;
 225  E :    ScopedHandle handle;
 226  E :    if (!GetClientInfo(binding, &pid, &handle))
 227  i :      return false;
 228    :  
 229  E :    Logger* instance = RpcLoggerInstanceManager::GetInstance();
 230  E :    if (!instance->Stop())
 231  i :      return false;
 232    :  
 233  E :    return true;
 234  E :  }

Coverage information generated Thu Jul 04 09:34:53 2013.