blob: 85278ea002f5f765fbad0bf5a1dcc2be5f2a6d92 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_GWP_ASAN_CRASH_HANDLER_CRASH_ANALYZER_H_
#define COMPONENTS_GWP_ASAN_CRASH_HANDLER_CRASH_ANALYZER_H_
#include <stddef.h>
#include "components/gwp_asan/common/allocator_state.h"
#include "components/gwp_asan/crash_handler/crash.pb.h"
#include "third_party/crashpad/crashpad/util/misc/address_types.h"
namespace crashpad {
class ExceptionSnapshot;
class ProcessMemory;
class ProcessSnapshot;
} // namespace crashpad
namespace gwp_asan {
namespace internal {
class CrashAnalyzer {
public:
// Captures the result of the GWP-ASan crash analyzer, whether the crash is
// determined to be related or unrelated to GWP-ASan or if an error was
// encountered analyzing the exception.
//
// These values are persisted via UMA--entries should not be renumbered and
// numeric values should never be reused.
enum class GwpAsanCrashAnalysisResult {
// The crash is not caused by GWP-ASan.
kUnrelatedCrash = 0,
// The crash is caused by GWP-ASan.
kGwpAsanCrash = 1,
// The ProcessMemory from the snapshot was null.
kErrorNullProcessMemory = 2,
// Failed to read the crashing process' memory of the global allocator.
kErrorFailedToReadAllocator = 3,
// The crashing process' global allocator members failed sanity checks.
kErrorAllocatorFailedSanityCheck = 4,
// Failed to read crash stack traces.
kErrorFailedToReadStackTrace = 5,
// The ExceptionSnapshot CPU context was null.
kErrorNullCpuContext = 6,
// The crashing process' bitness does not match the crash handler.
kErrorMismatchedBitness = 7,
// The allocator computed an invalid slot index.
kErrorBadSlot = 8,
// Failed to read the crashing process' memory of the SlotMetadata.
kErrorFailedToReadSlotMetadata = 9,
// Number of values in this enumeration, required by UMA.
kMaxValue = kErrorFailedToReadSlotMetadata
};
// Given a ProcessSnapshot, determine if the exception is related to GWP-ASan.
// If it is, return kGwpAsanCrash and fill out the info parameter with
// details about the exception. Otherwise, return a value indicating that the
// crash is unrelated or that an error occured.
static GwpAsanCrashAnalysisResult GetExceptionInfo(
const crashpad::ProcessSnapshot& process_snapshot,
gwp_asan::Crash* proto);
private:
using SlotMetadata = AllocatorState::SlotMetadata;
// Given an ExceptionSnapshot, return the address of where the exception
// occurred (or null if it was not a data access exception.)
static crashpad::VMAddress GetAccessAddress(
const crashpad::ExceptionSnapshot& exception);
// If the allocator annotation is present in the given snapshot, then return
// the address for the GuardedPageAllocator in the crashing process.
static crashpad::VMAddress GetAllocatorAddress(
const crashpad::ProcessSnapshot& process_snapshot);
// This method implements the underlying logic for GetExceptionInfo(). It
// analyzes the GuardedPageAllocator of the crashing process, and if the
// exception address is in the GWP-ASan region it fills out the protobuf
// parameter and returns kGwpAsanCrash.
static GwpAsanCrashAnalysisResult AnalyzeCrashedAllocator(
const crashpad::ProcessMemory& memory,
crashpad::VMAddress gpa_addr,
crashpad::VMAddress exception_addr,
gwp_asan::Crash* proto);
// This method fills out an AllocationInfo protobuf from a
// SlotMetadata::AllocationInfo struct.
static void ReadAllocationInfo(const SlotMetadata::AllocationInfo& slot_info,
gwp_asan::Crash_AllocationInfo* proto_info);
};
} // namespace internal
} // namespace gwp_asan
#endif // COMPONENTS_GWP_ASAN_CRASH_HANDLER_CRASH_ANALYZER_H_