forked from mirrors/gecko-dev
This changes comes with several different refactorings all rolled into one, unfotunately I couldn't find a way to pull them apart: - First of all annotations now can either recorded (that is, we copy the value and have the crash reporting code own the copy) or registered. Several annotations are changed to use this functionality so that we don't need to update them as their value change. - The code in the exception handler is modified to read the annotations from the mozannotation_client crate. This has the unfortunate side-effect that we need three different bits of code to serialize them: one for annotations read from a child process, one for reading annotations from the main process outside of the exception handler and one for reading annotations from the main process within the exception handler. As we move to fully out-of-process crash reporting the last two methods will go away. - The mozannotation_client crate now doesn't record annotation types anymore. I realized as I was working on this that storing types at runtime has two issues: the first one is that buggy code might change the type of an annotation (that is record it under two different types at two different moments), the second issue is that types might become corrupt during a crash, so better enforce them at annotation-writing time. The end result is that the mozannotation_* crates now only store byte buffers, track the format the data is stored in (null-terminated string, fixed size buffer, etc...) but not the type of data each annotation is supposed to contain. - Which brings us to the next change: concrete types for annotations are now enforced when they're written out. If an annotation doesn't match the expected type it's skipped. Storing an annotation with the wrong type will also trigger an assertion in debug builds. Differential Revision: https://phabricator.services.mozilla.com/D195248
123 lines
3.5 KiB
C
123 lines
3.5 KiB
C
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef CrashAnnotations_h
|
|
#define CrashAnnotations_h
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
|
|
namespace CrashReporter {
|
|
|
|
// Typed enum representing all crash annotations
|
|
enum class Annotation : uint32_t {
|
|
${enum}
|
|
};
|
|
|
|
// Stringified crash annotation names
|
|
const char* const kAnnotationStrings[] = {
|
|
${strings}
|
|
};
|
|
|
|
// Type of each annotation
|
|
enum class AnnotationType : uint8_t {
|
|
String = 0, // Any type of string, const char*, nsCString, etc...
|
|
Boolean = 1, // Stored as a byte
|
|
U32 = 2, // C/C++'s uint32_t or Rust's u32
|
|
U64 = 3, // C/C++'s uint64_t or Rust's u64
|
|
USize = 4, // C/C++'s size_t or Rust's usize
|
|
};
|
|
|
|
// Type of each annotation
|
|
const AnnotationType kAnnotationTypes[] = {
|
|
${types}
|
|
};
|
|
|
|
// Allowlist of crash annotations that can be included in a crash ping
|
|
const Annotation kCrashPingAllowedList[] = {
|
|
${allowedlist}
|
|
};
|
|
|
|
// Annotations which should be skipped when they have specific values
|
|
struct AnnotationSkipValue {
|
|
Annotation annotation;
|
|
const char* value;
|
|
};
|
|
|
|
const AnnotationSkipValue kSkipIfList[] = {
|
|
${skiplist}
|
|
};
|
|
|
|
/**
|
|
* Return the type of a crash annotation.
|
|
*
|
|
* @param aAnnotation a crash annotation
|
|
* @returns The type of this annotation
|
|
*/
|
|
static inline AnnotationType TypeOfAnnotation(Annotation aAnnotation) {
|
|
return kAnnotationTypes[static_cast<uint32_t>(aAnnotation)];
|
|
}
|
|
|
|
/**
|
|
* Return the string representation of a crash annotation.
|
|
*
|
|
* @param aAnnotation a crash annotation
|
|
* @returns A constant string holding the annotation name
|
|
*/
|
|
static inline const char* AnnotationToString(Annotation aAnnotation) {
|
|
return kAnnotationStrings[static_cast<uint32_t>(aAnnotation)];
|
|
}
|
|
|
|
/**
|
|
* Converts a string to its corresponding crash annotation.
|
|
*
|
|
* @param aResult a reference where the annotation will be stored
|
|
* @param aValue the string to be converted
|
|
* @return true if the string was successfully converted, false if it did not
|
|
* correspond to any known annotation
|
|
*/
|
|
bool AnnotationFromString(Annotation& aResult, const char* aValue);
|
|
|
|
/**
|
|
* Checks if the given crash annotation is allowed for inclusion in the crash
|
|
* ping.
|
|
*
|
|
* @param aAnnotation the crash annotation to be checked
|
|
* @return true if the annotation can be included in the crash ping, false
|
|
* otherwise
|
|
*/
|
|
bool IsAnnotationAllowedForPing(Annotation aAnnotation);
|
|
|
|
/**
|
|
* Checks if the annotation should be included. Some annotations are skipped if
|
|
* their value matches a specific one (like the value 0).
|
|
*
|
|
* @param aAnnotation the crash annotation to be checked
|
|
* @param aValue the contents of the annotation as a string
|
|
* @return true if the annotation should be included, false otherwise
|
|
*/
|
|
bool ShouldIncludeAnnotation(Annotation aAnnotation, const char* aValue);
|
|
|
|
/**
|
|
* Abstract annotation writer, this is needed only for code that writes out
|
|
* annotations in the exception handler.
|
|
*/
|
|
class AnnotationWriter {
|
|
public:
|
|
virtual void Write(Annotation aAnnotation, const char* aValue,
|
|
size_t aLen = 0) = 0;
|
|
virtual void Write(Annotation aAnnotation, bool aValue) = 0;
|
|
virtual void Write(Annotation aAnnotation, uint64_t aValue) = 0;
|
|
};
|
|
|
|
#ifdef XP_WIN
|
|
|
|
extern void RecordDllAnnotations(bool* aBlocklistInitFailed,
|
|
bool* aUser32BeforeBlocklist);
|
|
|
|
#endif // XP_WIN
|
|
|
|
} // namespace CrashReporter
|
|
|
|
#endif // CrashAnnotations_h
|