Coverage for /Syzygy/agent/asan/reporters/crashpad_reporter.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
67.6%50740.C++source

Line-by-line coverage:

   1    :  // Copyright 2016 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/reporters/crashpad_reporter.h"
  16    :  
  17    :  #include <algorithm>
  18    :  
  19    :  #include "base/environment.h"
  20    :  #include "base/strings/utf_string_conversions.h"
  21    :  #include "client/crashpad_client.h"
  22    :  
  23    :  namespace agent {
  24    :  namespace asan {
  25    :  namespace reporters {
  26    :  
  27    :  namespace {
  28    :  
  29    :  // The name of the environment variable that holds the crashpad pipe name.
  30    :  const char kCrashpadPipeNameVar[] = "CHROME_CRASHPAD_PIPE_NAME";
  31    :  
  32    :  // The crashpad client. This is used for communicating with the crashpad
  33    :  // process via IPC.
  34  E :  crashpad::CrashpadClient g_crashpad_client;
  35    :  
  36    :  // Used for establishing Crashpad IPC channels. This is racy, but the IPC
  37    :  // mechanism ensures everyone will get the same results and that it's
  38    :  // inherently safe. Barring people changing the environment variable between
  39    :  // calls. So, to be completely sure bring your own synchronization.
  40    :  // NOTE: This entire mechanism is... ugly. It relies on very specific knowledge
  41    :  // of how Chrome interacts with its instance of a Crashpad handler, and it
  42    :  // doesn't generalize to other clients. Moving forward we will be adding a
  43    :  // generic callback mechanism for instrumented clients to inform the RTL of the
  44    :  // crash handler to use.
  45  E :  bool EnsureCrashpadConnected() {
  46    :    static bool initialized = false;
  47    :    static bool crashpad_present = false;
  48    :  
  49    :    // Only initialize once.
  50  E :    if (initialized)
  51  E :      return crashpad_present;
  52  E :    initialized = true;
  53    :  
  54    :    // Get the name of the crashpad endpoint, failing if none exists.
  55  E :    std::unique_ptr<base::Environment> env(base::Environment::Create());
  56  E :    std::string pipe_name;
  57  E :    if (!env->GetVar(kCrashpadPipeNameVar, &pipe_name))
  58  E :      return false;
  59  i :    std::wstring pipe_name_w = base::UTF8ToWide(pipe_name);
  60    :  
  61    :    // Initialize the crashpad client.
  62  i :    if (!g_crashpad_client.SetHandlerIPCPipe(pipe_name_w))
  63  i :      return false;
  64  i :    if (!g_crashpad_client.UseHandler())
  65  i :      return false;
  66    :  
  67  i :    crashpad_present = true;
  68  i :    return true;
  69  E :  }
  70    :  
  71    :  }  // namespace
  72    :  
  73    :  const char CrashpadReporter::kName[] = "CrashpadReporter";
  74    :  
  75    :  // static
  76  E :  std::unique_ptr<CrashpadReporter> CrashpadReporter::Create() {
  77    :    // Create a crashpad reporter only if a crashpad instance is running for this
  78    :    // process.
  79  E :    if (!EnsureCrashpadConnected())
  80  E :      return nullptr;
  81    :  
  82  i :    auto crashpad_info = crashpad::CrashpadInfo::GetCrashpadInfo();
  83  i :    return std::unique_ptr<CrashpadReporter>(new CrashpadReporter(crashpad_info));
  84  E :  }
  85    :  
  86  E :  const char* CrashpadReporter::GetName() const {
  87  E :    return kName;
  88  E :  }
  89    :  
  90  E :  uint32_t CrashpadReporter::GetFeatures() const {
  91  E :    return FEATURE_CRASH_KEYS | FEATURE_EARLY_CRASH_KEYS |
  92    :        FEATURE_MEMORY_RANGES | FEATURE_CUSTOM_STREAMS |
  93    :        FEATURE_DUMP_WITHOUT_CRASH;
  94  E :  }
  95    :  
  96    :  bool CrashpadReporter::SetCrashKey(base::StringPiece key,
  97  E :                                     base::StringPiece value) {
  98  E :    DCHECK_NE(reinterpret_cast<crashpad::SimpleStringDictionary*>(nullptr),
  99  E :              crash_keys_.get());
 100    :  
 101    :    // StringPiece's aren't necessarily null terminated, so convert to
 102    :    // std::string first.
 103  E :    std::string k = key.as_string();
 104    :  
 105    :    // SetKeyValue fails silently when the dictionary is full. If we're out of
 106    :    // entries fail if this is a new key.
 107  E :    if (crash_keys_->GetCount() == crash_keys_->num_entries &&
 108    :        crash_keys_->GetValueForKey(k.c_str()) == nullptr) {
 109  E :      return false;
 110    :    }
 111    :  
 112    :    // Set the key if there's room.
 113  E :    std::string v = value.as_string();
 114  E :    crash_keys_->SetKeyValue(k.c_str(), v.c_str());
 115  E :    return true;
 116  E :  }
 117    :  
 118  E :  bool CrashpadReporter::SetMemoryRanges(const MemoryRanges& memory_ranges) {
 119  E :    auto crashpad_info = crashpad::CrashpadInfo::GetCrashpadInfo();
 120  E :    if (!crashpad_info)
 121  i :      return false;
 122    :  
 123    :    // Create a local bag of address ranges and populate it.
 124  E :    std::unique_ptr<crashpad::SimpleAddressRangeBag> ranges(
 125    :        new crashpad::SimpleAddressRangeBag());
 126    :  
 127    :    // Copy over as many ranges as will fit in the constrained
 128    :    // SimpleAddressRangeBag.
 129  E :    size_t count = std::min(memory_ranges.size(), ranges->num_entries);
 130  E :    for (size_t i = 0; i < count; ++i) {
 131  E :      const auto& range = memory_ranges[i];
 132  E :      ranges->Insert(crashpad::CheckedRange<uint64_t>(
 133    :          reinterpret_cast<uint32_t>(range.first), range.second));
 134  E :    }
 135    :  
 136    :    // Swap out the old bag for the new.
 137  E :    crash_ranges_.reset(ranges.release());
 138  E :    crashpad_info->set_extra_memory_ranges(crash_ranges_.get());
 139    :  
 140    :    // Return success only if all of the ranges were set.
 141  E :    return count == memory_ranges.size();
 142  E :  }
 143    :  
 144    :  bool CrashpadReporter::SetCustomStream(uint32_t stream_type,
 145    :                                         const uint8_t* stream_data,
 146  i :                                         size_t stream_length) {
 147  i :    auto crashpad_info = crashpad::CrashpadInfo::GetCrashpadInfo();
 148  i :    if (!crashpad_info)
 149  i :      return false;
 150  i :    crashpad_info->AddUserDataMinidumpStream(
 151    :        stream_type, stream_data, stream_length);
 152  i :    return true;
 153  i :  }
 154    :  
 155    :  // Crashes the running process and sends a crash report.
 156  i :  void CrashpadReporter::DumpAndCrash(EXCEPTION_POINTERS* exception_pointers) {
 157  i :    g_crashpad_client.DumpAndCrash(exception_pointers);
 158    :  
 159    :    // The crash function shouldn't return, but putting a NOTREACHED here makes
 160    :    // this function difficult to test.
 161  i :  }
 162    :  
 163  i :  bool CrashpadReporter::DumpWithoutCrash(const CONTEXT& context) {
 164  i :    g_crashpad_client.DumpWithoutCrash(context);
 165  i :    return true;
 166  i :  }
 167    :  
 168    :  CrashpadReporter::CrashpadReporter(crashpad::CrashpadInfo* crashpad_info)
 169  E :      : crashpad_info_(crashpad_info) {
 170  E :    crash_keys_.reset(new crashpad::SimpleStringDictionary());
 171    :  
 172    :    // Initialize the crashpad info struct. Limit indirectly referenced memory to
 173    :    // a maximum of 1MB, so that crash reports come in at around 1.5-1.7MB. This
 174    :    // is similar to the size of SyzyAsan crash reports generated by MS tools.
 175  E :    crashpad_info->set_crashpad_handler_behavior(
 176    :        crashpad::TriState::kEnabled);
 177  E :    crashpad_info->set_system_crash_reporter_forwarding(
 178    :        crashpad::TriState::kDisabled);
 179  E :    crashpad_info->set_gather_indirectly_referenced_memory(
 180    :        crashpad::TriState::kEnabled, 1 * 1024 * 1024);
 181  E :    crashpad_info->set_simple_annotations(crash_keys_.get());
 182  E :  }
 183    :  
 184    :  }  // namespace reporters
 185    :  }  // namespace asan
 186    :  }  // namespace agent

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