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

Coverage information generated Fri Jul 29 11:00:21 2016.