Coverage for /Syzygy/kasko/api/reporter.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
0.0%00141.C++source

Line-by-line coverage:

   1    :  // Copyright 2014 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/kasko/api/reporter.h"
  16    :  
  17    :  #include <stdint.h>
  18    :  
  19    :  #include <map>
  20    :  #include <memory>
  21    :  #include <vector>
  22    :  
  23    :  #include "base/bind.h"
  24    :  #include "base/bind_helpers.h"
  25    :  #include "base/environment.h"
  26    :  #include "base/logging.h"
  27    :  #include "base/files/file_path.h"
  28    :  #include "base/strings/string_number_conversions.h"
  29    :  #include "base/time/time.h"
  30    :  #include "base/win/scoped_handle.h"
  31    :  #include "syzygy/kasko/dll_lifetime.h"
  32    :  #include "syzygy/kasko/minidump.h"
  33    :  #include "syzygy/kasko/minidump_request.h"
  34    :  #include "syzygy/kasko/reporter.h"
  35    :  #include "syzygy/kasko/api/crash_key.h"
  36    :  #include "syzygy/kasko/api/internal/crash_key_registration.h"
  37    :  
  38  m :  namespace kasko {
  39  m :  namespace api {
  40  m :  namespace {
  41    :  
  42    :  // Default upload and retry times. These can be overridden by an environment
  43    :  // variable.
  44  m :  const uint16_t kDefaultUploadDelayInSeconds = 180;
  45  m :  const uint16_t kDefaultRetryIntervalInMinutes = 180;
  46    :  
  47    :  // Environment variables for overriding the above times.
  48  m :  const char kEnvUploadDelayInSeconds[] = "KASKO_UPLOAD_DELAY_IN_SECONDS";
  49  m :  const char kEnvRetryIntervalInMinutes[] = "KASKO_RETRY_INTERVAL_IN_MINUTES";
  50    :  
  51  m :  const DllLifetime* g_dll_lifetime;
  52  m :  Reporter* g_reporter;
  53    :  
  54  m :  void InvokeOnUploadProc(
  55  m :      OnUploadProc* on_upload_proc,
  56  m :      void* on_upload_context,
  57  m :      const base::string16& report_id,
  58  m :      const base::FilePath& minidump_path,
  59  m :      const std::map<base::string16, base::string16>& crash_keys) {
  60  m :    std::vector<const base::char16*> crash_key_names;
  61  m :    std::vector<const base::char16*> crash_key_values;
  62  m :    crash_key_names.reserve(crash_keys.size() + 1);
  63  m :    crash_key_values.reserve(crash_keys.size() + 1);
  64    :  
  65  m :    for (const auto& entry : crash_keys) {
  66  m :      crash_key_names.push_back(entry.first.c_str());
  67  m :      crash_key_values.push_back(entry.second.c_str());
  68  m :    }
  69  m :    crash_key_names.push_back(nullptr);
  70  m :    crash_key_values.push_back(nullptr);
  71    :  
  72  m :    on_upload_proc(on_upload_context, report_id.c_str(),
  73  m :                   minidump_path.value().c_str(), crash_key_names.data(),
  74  m :                   crash_key_values.data());
  75  m :  }
  76    :  
  77    :  // Returns an integer value from the environment. If not present or malformed,
  78    :  // returns the specified default. Only allows positive values.
  79  m :  int64_t GetIntegerFromEnvironment(const char* key_name,
  80  m :                                    int64_t default_value) {
  81  m :    std::unique_ptr<base::Environment> env(base::Environment::Create());
  82  m :    std::string value;
  83  m :    if (!env->GetVar(key_name, &value))
  84  m :      return default_value;
  85    :  
  86  m :    int64_t i = 0;
  87  m :    if (!base::StringToInt64(value, &i))
  88  m :      return default_value;
  89    :  
  90  m :    if (i <= 0)
  91  m :      return default_value;
  92    :  
  93  m :    return i;
  94  m :  }
  95    :  
  96  m :  }  // namespace
  97    :  
  98  m :  const base::char16* const kPermanentFailureCrashKeysExtension =
  99  m :      Reporter::kPermanentFailureCrashKeysExtension;
 100  m :  const base::char16* const kPermanentFailureMinidumpExtension =
 101  m :      Reporter::kPermanentFailureMinidumpExtension;
 102    :  
 103  m :  bool InitializeReporter(const base::char16* endpoint_name,
 104  m :                          const base::char16* url,
 105  m :                          const base::char16* data_directory,
 106  m :                          const base::char16* permanent_failure_directory,
 107  m :                          OnUploadProc* on_upload_proc,
 108  m :                          void* on_upload_context) {
 109  m :    DCHECK(!g_dll_lifetime);
 110  m :    g_dll_lifetime = new DllLifetime;
 111    :  
 112  m :    Reporter::OnUploadCallback on_upload_callback;
 113    :  
 114  m :    if (on_upload_proc) {
 115  m :      on_upload_callback =
 116  m :          base::Bind(&InvokeOnUploadProc, base::Unretained(on_upload_proc),
 117  m :                     base::Unretained(on_upload_context));
 118  m :    }
 119    :  
 120    :  
 121  m :    int64_t upload_delay = GetIntegerFromEnvironment(
 122  m :        kEnvUploadDelayInSeconds, kDefaultUploadDelayInSeconds);
 123  m :    int64_t retry_interval = GetIntegerFromEnvironment(
 124  m :        kEnvRetryIntervalInMinutes, kDefaultRetryIntervalInMinutes);
 125  m :    DCHECK(!g_reporter);
 126  m :    g_reporter =
 127  m :        Reporter::Create(endpoint_name, url, base::FilePath(data_directory),
 128  m :                         base::FilePath(permanent_failure_directory),
 129  m :                         base::TimeDelta::FromSeconds(upload_delay),
 130  m :                         base::TimeDelta::FromMinutes(retry_interval),
 131  m :                         on_upload_callback)
 132  m :            .release();
 133    :  
 134  m :    return g_reporter != nullptr;
 135  m :  }
 136    :  
 137  m :  void SendReportForProcess(base::ProcessHandle process_handle,
 138  m :                            base::PlatformThreadId thread_id,
 139  m :                            const EXCEPTION_POINTERS* exception_pointers,
 140  m :                            MinidumpType minidump_type,
 141  m :                            const base::char16* const* keys,
 142  m :                            const base::char16* const* values) {
 143  m :    DCHECK(g_reporter);
 144  m :    if (!g_reporter)
 145  m :      return;
 146  m :    DCHECK_EQ(keys == nullptr, values == nullptr);
 147    :  
 148  m :    MinidumpRequest request;
 149    :  
 150  m :    request.exception_info_address =
 151  m :        reinterpret_cast<uint32_t>(exception_pointers);
 152    :  
 153  m :    if (keys != nullptr && values != nullptr) {
 154  m :      size_t i = 0;
 155  m :      for (; keys[i] && values[i]; ++i) {
 156  m :        if (keys[i][0] == 0 || values[i][0] == 0)
 157  m :          continue;
 158  m :        request.crash_keys.push_back(
 159  m :            MinidumpRequest::CrashKey(keys[i], values[i]));
 160  m :      }
 161  m :      DCHECK(!keys[i]);
 162  m :      DCHECK(!values[i]);
 163  m :    }
 164    :  
 165    :    // Reopen the process handle with the necessary access level to read memory
 166    :    // and create a minidump.
 167  m :    base::win::ScopedHandle augmented_process_handle(
 168  m :        ::OpenProcess(GetRequiredAccessForMinidumpType(minidump_type), FALSE,
 169  m :                      base::GetProcId(process_handle)));
 170  m :    if (!augmented_process_handle.IsValid())
 171  m :      return;
 172    :  
 173  m :    std::vector<CrashKey> registered_crash_keys;
 174  m :    if (internal::ReadCrashKeysFromProcess(augmented_process_handle.Get(),
 175  m :                                           &registered_crash_keys)) {
 176  m :      for (auto& crash_key : registered_crash_keys) {
 177  m :        if (crash_key.name[0] == 0 || crash_key.value[0] == 0)
 178  m :          continue;
 179  m :        request.crash_keys.push_back(
 180  m :            MinidumpRequest::CrashKey(crash_key.name, crash_key.value));
 181  m :      }
 182  m :    }
 183    :  
 184  m :    switch (minidump_type) {
 185  m :      case SMALL_DUMP_TYPE:
 186  m :        request.type = MinidumpRequest::SMALL_DUMP_TYPE;
 187  m :        break;
 188  m :      case LARGER_DUMP_TYPE:
 189  m :        request.type = MinidumpRequest::LARGER_DUMP_TYPE;
 190  m :        break;
 191  m :      case FULL_DUMP_TYPE:
 192  m :        request.type = MinidumpRequest::FULL_DUMP_TYPE;
 193  m :        break;
 194  m :      default:
 195  m :        NOTREACHED();
 196  m :        break;
 197  m :    }
 198    :  
 199  m :    g_reporter->SendReportForProcess(augmented_process_handle.Get(), thread_id,
 200  m :                                     request);
 201  m :  }
 202    :  
 203  m :  void ShutdownReporter() {
 204  m :    std::unique_ptr<Reporter> reporter(g_reporter);
 205  m :    g_reporter = nullptr;
 206  m :    Reporter::Shutdown(std::move(reporter));
 207    :  
 208  m :    DCHECK(g_dll_lifetime);
 209  m :    delete g_dll_lifetime;
 210  m :    g_dll_lifetime = nullptr;
 211  m :  }
 212    :  
 213  m :  }  // namespace api
 214  m :  }  // namespace kasko

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