Coverage for /Syzygy/agent/asan/logger.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
98.5%64650.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/asan/logger.h"
  16    :  
  17    :  #include "base/command_line.h"
  18    :  #include "base/environment.h"
  19    :  #include "base/logging.h"
  20    :  #include "base/debug/stack_trace.h"
  21    :  #include "base/memory/scoped_ptr.h"
  22    :  #include "base/process/launch.h"
  23    :  #include "base/strings/stringprintf.h"
  24    :  #include "base/strings/utf_string_conversions.h"
  25    :  #include "syzygy/common/rpc/helpers.h"
  26    :  #include "syzygy/trace/rpc/logger_rpc.h"
  27    :  
  28    :  namespace agent {
  29    :  namespace asan {
  30    :  
  31    :  namespace {
  32    :  
  33    :  using ::common::rpc::GetInstanceString;
  34    :  
  35    :  AsanLogger* logger_instance = NULL;
  36    :  
  37    :  void InitExecutionContext(const CONTEXT& rtl_context,
  38  E :                            ExecutionContext* exc_context) {
  39  E :    DCHECK(exc_context != NULL);
  40    :  
  41  E :    exc_context->edi = rtl_context.Edi;
  42  E :    exc_context->esi = rtl_context.Esi;
  43  E :    exc_context->ebx = rtl_context.Ebx;
  44  E :    exc_context->edx = rtl_context.Edx;
  45  E :    exc_context->ecx = rtl_context.Ecx;
  46  E :    exc_context->eax = rtl_context.Eax;
  47  E :    exc_context->ebp = rtl_context.Ebp;
  48  E :    exc_context->eip = rtl_context.Eip;
  49  E :    exc_context->seg_cs = rtl_context.SegCs;
  50  E :    exc_context->eflags = rtl_context.EFlags;
  51  E :    exc_context->esp = rtl_context.Esp;
  52  E :    exc_context->seg_ss = rtl_context.SegSs;
  53  E :  }
  54    :  
  55    :  }  // namespace
  56    :  
  57  E :  AsanLogger::AsanLogger() : log_as_text_(true), minidump_on_failure_(false) {
  58  E :  }
  59    :  
  60  E :  void AsanLogger::Init() {
  61    :    bool success = rpc_binding_.Open(
  62    :        kLoggerRpcProtocol,
  63  E :        GetInstanceString(kLoggerRpcEndpointRoot, instance_id_));
  64    :  
  65    :    // TODO(rogerm): Add a notion of a session to the logger interface. Opening
  66    :    //     a session (either here, or on first use) allows for better management
  67    :    //     of symbol context across trace log messages for a given process.
  68  E :    if (success) {
  69    :      const base::CommandLine* command_line =
  70  E :          base::CommandLine::ForCurrentProcess();
  71    :      std::string message = base::StringPrintf(
  72    :          "PID=%d; cmd-line='%ls'\n",
  73    :          ::GetCurrentProcessId(),
  74  E :          command_line->GetCommandLineString().c_str());
  75    :      success = ::common::rpc::InvokeRpc(&LoggerClient_Write, rpc_binding_.Get(),
  76    :                                         reinterpret_cast<const unsigned char*>(
  77  E :                                             message.c_str())).succeeded();
  78  E :      if (!success)
  79  E :        rpc_binding_.Close();
  80  E :    }
  81  E :  }
  82    :  
  83  E :  void AsanLogger::Stop() {
  84  E :    if (rpc_binding_.Get() != NULL) {
  85  E :      ::common::rpc::InvokeRpc(&LoggerClient_Stop, rpc_binding_.Get());
  86    :    }
  87  E :  }
  88    :  
  89  E :  void AsanLogger::Write(const std::string& message) {
  90    :    // If we're bound to a logging endpoint, log the message there.
  91  E :    if (rpc_binding_.Get() != NULL) {
  92    :      ::common::rpc::InvokeRpc(
  93    :          &LoggerClient_Write, rpc_binding_.Get(),
  94  E :          reinterpret_cast<const unsigned char*>(message.c_str()));
  95    :    }
  96  E :  }
  97    :  
  98    :  void AsanLogger::WriteWithContext(const std::string& message,
  99  E :                                    const CONTEXT& context) {
 100    :    // If we're bound to a logging endpoint, log the message there.
 101  E :    if (rpc_binding_.Get() != NULL) {
 102  E :      ExecutionContext exec_context = {};
 103  E :      InitExecutionContext(context, &exec_context);
 104    :      ::common::rpc::InvokeRpc(
 105    :          &LoggerClient_WriteWithContext, rpc_binding_.Get(),
 106  E :          reinterpret_cast<const unsigned char*>(message.c_str()), &exec_context);
 107    :    }
 108  E :  }
 109    :  
 110    :  void AsanLogger::WriteWithStackTrace(const std::string& message,
 111    :                                       const void * const * trace_data,
 112  E :                                       size_t trace_length) {
 113    :    // If we're bound to a logging endpoint, log the message there.
 114  E :    if (rpc_binding_.Get() != NULL) {
 115    :      ::common::rpc::InvokeRpc(
 116    :          &LoggerClient_WriteWithTrace, rpc_binding_.Get(),
 117    :          reinterpret_cast<const unsigned char*>(message.c_str()),
 118  E :          reinterpret_cast<const DWORD*>(trace_data), trace_length);
 119    :    }
 120  E :  }
 121    :  
 122    :  void AsanLogger::SaveMinidumpWithProtobufAndMemoryRanges(
 123    :      CONTEXT* context,
 124    :      AsanErrorInfo* error_info,
 125    :      const std::string& protobuf,
 126  E :      const MemoryRanges& memory_ranges) {
 127  E :    CHECK_NE(static_cast<CONTEXT*>(nullptr), context);
 128  E :    CHECK_NE(static_cast<AsanErrorInfo*>(nullptr), error_info);
 129    :  
 130  E :    if (rpc_binding_.Get() == NULL)
 131  i :      return;
 132    :  
 133    :    // Convert the memory ranges to arrays.
 134  E :    std::vector<const void*> base_addresses;
 135  E :    std::vector<size_t> range_lengths;
 136  E :    for (const auto& val : memory_ranges) {
 137  E :      base_addresses.push_back(val.first);
 138  E :      range_lengths.push_back(val.second);
 139  E :    }
 140    :  
 141  E :    EXCEPTION_RECORD exception = {};
 142  E :    exception.ExceptionCode = EXCEPTION_ARRAY_BOUNDS_EXCEEDED;
 143  E :    exception.ExceptionAddress = reinterpret_cast<PVOID>(context->Eip);
 144  E :    exception.NumberParameters = 2;
 145  E :    exception.ExceptionInformation[0] = reinterpret_cast<ULONG_PTR>(context);
 146  E :    exception.ExceptionInformation[1] = reinterpret_cast<ULONG_PTR>(error_info);
 147    :  
 148  E :    const EXCEPTION_POINTERS pointers = { &exception, context };
 149    :    ::common::rpc::InvokeRpc(
 150    :        &LoggerClient_SaveMinidumpWithProtobufAndMemoryRanges, rpc_binding_.Get(),
 151    :        ::GetCurrentThreadId(), reinterpret_cast<unsigned long>(&pointers),
 152    :        reinterpret_cast<const byte*>(protobuf.data()),
 153    :        static_cast<unsigned long>(protobuf.size()),
 154    :        reinterpret_cast<const unsigned long*>(base_addresses.data()),
 155    :        reinterpret_cast<const unsigned long*>(range_lengths.data()),
 156  E :        memory_ranges.size());
 157  E :  }
 158    :  
 159    :  }  // namespace asan
 160    :  }  // namespace agent

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