summaryrefslogtreecommitdiffstats
path: root/toolkit/crashreporter
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:33 +0000
commit086c044dc34dfc0f74fbe41f4ecb402b2cd34884 (patch)
treea4f824bd33cb075dd5aa3eb5a0a94af221bbe83a /toolkit/crashreporter
parentAdding debian version 124.0.1-1. (diff)
downloadfirefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.tar.xz
firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.zip
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'toolkit/crashreporter')
-rw-r--r--toolkit/crashreporter/CrashAnnotations.h.in18
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc4
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc12
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h9
-rw-r--r--toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc12
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc15
-rw-r--r--toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h3
-rw-r--r--toolkit/crashreporter/docs/index.rst5
-rw-r--r--toolkit/crashreporter/linux_utils.cc59
-rw-r--r--toolkit/crashreporter/linux_utils.h16
-rw-r--r--toolkit/crashreporter/moz.build8
-rw-r--r--toolkit/crashreporter/mozannotation_client/src/lib.rs257
-rw-r--r--toolkit/crashreporter/mozannotation_server/Cargo.toml1
-rw-r--r--toolkit/crashreporter/mozannotation_server/src/lib.rs66
-rw-r--r--toolkit/crashreporter/mozannotation_server/src/process_reader/linux.rs4
-rw-r--r--toolkit/crashreporter/nsDummyExceptionHandler.cpp71
-rw-r--r--toolkit/crashreporter/nsExceptionHandler.cpp678
-rw-r--r--toolkit/crashreporter/nsExceptionHandler.h47
-rw-r--r--toolkit/crashreporter/test/gtest/TestElfSoVersion.cpp143
-rw-r--r--toolkit/crashreporter/test/gtest/moz.build16
-rw-r--r--toolkit/crashreporter/test/moz.build4
-rw-r--r--toolkit/crashreporter/test/unit/head_crashreporter.js3
-rw-r--r--toolkit/crashreporter/test/unit/test_crash_modules_linux.js33
-rw-r--r--toolkit/crashreporter/test/unit/xpcshell-phc.toml4
-rw-r--r--toolkit/crashreporter/test/unit/xpcshell.toml40
-rwxr-xr-xtoolkit/crashreporter/tools/symbolstore.py2
26 files changed, 1095 insertions, 435 deletions
diff --git a/toolkit/crashreporter/CrashAnnotations.h.in b/toolkit/crashreporter/CrashAnnotations.h.in
index 7ea8c98bc1..2288498f36 100644
--- a/toolkit/crashreporter/CrashAnnotations.h.in
+++ b/toolkit/crashreporter/CrashAnnotations.h.in
@@ -50,6 +50,16 @@ ${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
@@ -97,9 +107,17 @@ 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
diff --git a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
index 8f25b7be02..2c2e24e071 100644
--- a/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/microdump_writer/microdump_writer.cc
@@ -466,8 +466,8 @@ class MicrodumpWriter {
char file_name[NAME_MAX];
char file_path[NAME_MAX];
- dumper_->GetMappingEffectiveNameAndPath(
- mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
+ dumper_->GetMappingEffectiveNamePathAndVersion(
+ mapping, file_path, sizeof(file_path), file_name, sizeof(file_name), nullptr);
LogAppend("M ");
LogAppend(static_cast<uintptr_t>(mapping.start_addr));
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
index 3b400ce8ca..ef05583397 100644
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.cc
@@ -468,11 +468,12 @@ bool ElfFileSoName(const LinuxDumper& dumper,
} // namespace
-void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
+void LinuxDumper::GetMappingEffectiveNamePathAndVersion(const MappingInfo& mapping,
char* file_path,
size_t file_path_size,
char* file_name,
- size_t file_name_size) {
+ size_t file_name_size,
+ uint32_t* version) {
my_strlcpy(file_path, mapping.name, file_path_size);
// Tools such as minidump_stackwalk use the name of the module to look up
@@ -487,6 +488,9 @@ void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
const char* basename = my_strrchr(file_path, '/');
basename = basename == NULL ? file_path : (basename + 1);
my_strlcpy(file_name, basename, file_name_size);
+ if (version) {
+ ElfFileSoVersion(mapping.name, version);
+ }
return;
}
@@ -512,6 +516,10 @@ void LinuxDumper::GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
my_strlcpy(file_path, file_name, file_path_size);
}
}
+
+ if (version) {
+ ElfFileSoVersion(mapping.name, version);
+ }
}
bool LinuxDumper::ReadAuxv() {
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
index 7155524ffc..7fd0693968 100644
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/linux_dumper.h
@@ -56,6 +56,10 @@
#include "common/memory_allocator.h"
#include "google_breakpad/common/minidump_format.h"
+#if defined(XP_LINUX)
+# include "linux_utils.h"
+#endif // defined(XP_LINUX)
+
namespace google_breakpad {
// Typedef for our parsing of the auxv variables in /proc/pid/auxv.
@@ -213,11 +217,12 @@ class LinuxDumper {
// other cases, however, a library can be mapped from an archive (e.g., when
// loading .so libs from an apk on Android) and this method is able to
// reconstruct the original file name.
- void GetMappingEffectiveNameAndPath(const MappingInfo& mapping,
+ void GetMappingEffectiveNamePathAndVersion(const MappingInfo& mapping,
char* file_path,
size_t file_path_size,
char* file_name,
- size_t file_name_size);
+ size_t file_name_size,
+ uint32_t* version);
protected:
bool ReadAuxv();
diff --git a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
index 03066e9110..60d1195949 100644
--- a/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
+++ b/toolkit/crashreporter/breakpad-client/linux/minidump_writer/minidump_writer.cc
@@ -717,8 +717,16 @@ class MinidumpWriter {
char file_name[NAME_MAX];
char file_path[NAME_MAX];
- dumper_->GetMappingEffectiveNameAndPath(
- mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
+ uint32_t version[4] = { 0, 0, 0, 0 };
+ dumper_->GetMappingEffectiveNamePathAndVersion(
+ mapping, file_path, sizeof(file_path), file_name, sizeof(file_name), version);
+
+ mod->version_info.signature = MD_VSFIXEDFILEINFO_SIGNATURE;
+ mod->version_info.struct_version |= MD_VSFIXEDFILEINFO_VERSION;
+ mod->version_info.file_version_hi = version[0];
+ mod->version_info.file_version_lo = version[1];
+ mod->version_info.product_version_hi = version[2];
+ mod->version_info.product_version_lo = version[3];
MDLocationDescriptor ld;
if (!minidump_writer_.WriteString(file_path, my_strlen(file_path), &ld))
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc
index e13e4509b0..64c01bdce4 100644
--- a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.cc
@@ -83,7 +83,7 @@ MinidumpGenerator::MinidumpGenerator()
cpu_type_(DynamicImages::GetNativeCPUType()),
dyldImageLoadAddress_(NULL),
dyldSlide_(0),
- dyldPath_(),
+ dyldPath_(nullptr),
task_context_(NULL),
dynamic_images_(NULL),
memory_blocks_(&allocator_) {
@@ -105,7 +105,7 @@ MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task,
cpu_type_(DynamicImages::GetNativeCPUType()),
dyldImageLoadAddress_(NULL),
dyldSlide_(0),
- dyldPath_(),
+ dyldPath_(nullptr),
task_context_(NULL),
dynamic_images_(NULL),
memory_blocks_(&allocator_) {
@@ -250,7 +250,7 @@ void MinidumpGenerator::GatherCurrentProcessDyldInformation() {
return;
}
dyldImageLoadAddress_ = mh;
- dyldPath_ = string(aii->dyldPath);
+ dyldPath_ = aii->dyldPath;
dyldSlide_ = GetCurrentProcessModuleSlide(mh, aii->sharedCacheSlide);
}
@@ -1464,7 +1464,7 @@ bool MinidumpGenerator::WriteModuleStream(unsigned int index,
if (index == INT_MAX) {
dyld_or_in_dyld_shared_cache = true;
slide = dyldSlide_;
- name = dyldPath_.c_str();
+ name = dyldPath_;
} else {
dyld_or_in_dyld_shared_cache =
((header->flags & MH_SHAREDCACHE) != 0);
@@ -1993,7 +1993,7 @@ bool MinidumpGenerator::WriteCrashInfoStream(
bool dyld_or_in_dyld_shared_cache;
if (i == image_count - 1) {
slide = dyldSlide_;
- module_path = dyldPath_.c_str();
+ module_path = dyldPath_;
dyld_or_in_dyld_shared_cache = true;
} else {
slide = _dyld_get_image_vmaddr_slide(i);
@@ -2048,7 +2048,10 @@ bool MinidumpGenerator::WriteBootargsStream(
int rv = sysctlbyname("kern.bootargs", NULL, &size, NULL, 0);
if ((rv != 0) || (size == 0))
size = 1;
- vector<uint8_t> bootargs(size);
+
+ wasteful_vector<uint8_t> bootargs(&this->allocator_, size);
+ bootargs.resize(size, 0);
+
bootargs[0] = 0;
if (rv == 0)
sysctlbyname("kern.bootargs", &bootargs[0], &size, NULL, 0);
diff --git a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h
index aba067cc04..77c250ccd5 100644
--- a/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h
+++ b/toolkit/crashreporter/breakpad-client/mac/handler/minidump_generator.h
@@ -266,7 +266,8 @@ class MinidumpGenerator {
// process has crashed.
breakpad_mach_header* dyldImageLoadAddress_;
ptrdiff_t dyldSlide_;
- string dyldPath_;
+ // We don't own this pointer, this is owned by macOS internal structures.
+ const char* dyldPath_;
// Context of the task to dump.
breakpad_ucontext_t *task_context_;
diff --git a/toolkit/crashreporter/docs/index.rst b/toolkit/crashreporter/docs/index.rst
index f2444a75c6..fe1af45d8f 100644
--- a/toolkit/crashreporter/docs/index.rst
+++ b/toolkit/crashreporter/docs/index.rst
@@ -66,7 +66,8 @@ a ``google_breakpad::ExceptionHandler`` instance and it's stored as
As the application runs, various other systems may write *annotations*
or *notes* to the crash reporter to indicate state of the application,
help with possible reasons for a current or future crash, etc. These are
-performed via ``CrashReporter::AnnotateCrashReport()`` and
+performed via ``CrashReporter::RecordAnnotation*()``,
+``CrashReporter::RegisterAnnotation*()`` functions and
``CrashReporter::AppendAppNotesToCrashReport()`` from
``nsExceptionHandler.h``.
@@ -154,7 +155,7 @@ with information about the crash.
Submission of child process crashes is handled by application code. This
code prompts the user to submit crashes in context-appropriate UI and then
-submits the crashes using ``CrashSubmit.jsm``.
+submits the crashes using ``CrashSubmit.sys.mjs``.
Memory Reports
==============
diff --git a/toolkit/crashreporter/linux_utils.cc b/toolkit/crashreporter/linux_utils.cc
new file mode 100644
index 0000000000..cfddecf084
--- /dev/null
+++ b/toolkit/crashreporter/linux_utils.cc
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "common/linux/linux_libc_support.h"
+#include "linux_utils.h"
+
+bool ElfFileSoVersion(const char* mapping_name, uint32_t* version_components) {
+ if (!version_components) {
+ return false;
+ }
+
+ // We found no version so just report 0
+ const char* so_version = my_strstr(mapping_name, ".so.");
+ if (so_version == nullptr) {
+ return true;
+ }
+
+ char tmp[12]; // 11 for maximum representation of UINT32T_MAX + \0 ?
+ size_t current_position = 0;
+ size_t next_tmp = 0;
+ tmp[0] = '\0';
+ for (size_t so_version_pos = 0; so_version_pos <= my_strlen(so_version);
+ ++so_version_pos) {
+ // We can't have more than four: MAJOR.minor.release.patch
+ if (current_position == 4) {
+ break;
+ }
+
+ char c = so_version[so_version_pos];
+ if (c != '.') {
+ if ((c <= '9' && c >= '0')) {
+ tmp[next_tmp] = c;
+ tmp[next_tmp + 1] = '\0';
+ ++next_tmp;
+ }
+
+ if (so_version[so_version_pos + 1] != '\0') {
+ continue;
+ }
+ }
+
+ if (my_strlen(tmp) > 0) {
+ int t;
+ if (!my_strtoui(&t, tmp)) {
+ return false;
+ }
+ uint32_t casted_tmp = (uint32_t)t;
+ version_components[current_position] = casted_tmp;
+ ++current_position;
+ }
+
+ tmp[0] = '\0';
+ next_tmp = 0;
+ }
+
+ return true;
+}
diff --git a/toolkit/crashreporter/linux_utils.h b/toolkit/crashreporter/linux_utils.h
new file mode 100644
index 0000000000..2dd4ff785c
--- /dev/null
+++ b/toolkit/crashreporter/linux_utils.h
@@ -0,0 +1,16 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 toolkit_breakpad_linux_utils_h__
+#define toolkit_breakpad_linux_utils_h__
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+bool ElfFileSoVersion(const char* mapping_name, uint32_t* version);
+
+#endif /* toolkit_breakpad_linux_utils_h__ */
diff --git a/toolkit/crashreporter/moz.build b/toolkit/crashreporter/moz.build
index d6f49680e7..952ca405bb 100644
--- a/toolkit/crashreporter/moz.build
+++ b/toolkit/crashreporter/moz.build
@@ -55,6 +55,14 @@ if CONFIG["MOZ_CRASHREPORTER"]:
"google-breakpad/src/processor",
]
+ UNIFIED_SOURCES += [
+ "linux_utils.cc",
+ ]
+
+ EXPORTS += [
+ "linux_utils.h",
+ ]
+
if CONFIG["MOZ_OXIDIZED_BREAKPAD"]:
DIRS += ["rust_minidump_writer_linux"]
diff --git a/toolkit/crashreporter/mozannotation_client/src/lib.rs b/toolkit/crashreporter/mozannotation_client/src/lib.rs
index 17fe017095..df2bd5bf94 100644
--- a/toolkit/crashreporter/mozannotation_client/src/lib.rs
+++ b/toolkit/crashreporter/mozannotation_client/src/lib.rs
@@ -3,30 +3,53 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
use nsstring::nsCString;
-use std::{ffi::c_void, sync::Mutex};
+use std::{
+ alloc::{self, Layout},
+ cmp::min,
+ ffi::{c_char, c_void, CStr},
+ ptr::{copy_nonoverlapping, null_mut},
+ sync::Mutex,
+};
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::arch::global_asm;
#[repr(C)]
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AnnotationContents {
Empty,
- NSCString,
+ NSCStringPointer,
+ CStringPointer,
CString,
- CharBuffer,
- USize,
ByteBuffer(u32),
+ OwnedByteBuffer(u32),
}
-
#[repr(C)]
-#[derive(Clone, Copy)]
pub struct Annotation {
pub id: u32,
pub contents: AnnotationContents,
pub address: usize,
}
+impl Drop for Annotation {
+ fn drop(&mut self) {
+ match self.contents {
+ AnnotationContents::OwnedByteBuffer(len) => {
+ if (self.address != 0) && (len > 0) {
+ let align = min(usize::next_power_of_two(len as usize), 32);
+ unsafe {
+ let layout = Layout::from_size_align_unchecked(len as usize, align);
+ alloc::dealloc(self.address as *mut u8, layout);
+ }
+ }
+ }
+ _ => {
+ // Nothing to do
+ }
+ };
+ }
+}
+
pub struct AnnotationTable {
data: Vec<Annotation>,
magic_number: u32,
@@ -222,98 +245,126 @@ pub struct MozAnnotationNote {
pub ehdr: isize,
}
-/// Register an annotation containing an nsCString.
-/// Returns false if the annotation is already present (and doesn't change it).
+fn store_annotation<T>(id: u32, contents: AnnotationContents, address: *const T) -> *const T {
+ let address = match contents {
+ AnnotationContents::OwnedByteBuffer(len) => {
+ if !address.is_null() && (len > 0) {
+ // Copy the contents of this annotation, we'll own the copy
+ let len = len as usize;
+ let align = min(usize::next_power_of_two(len), 32);
+ unsafe {
+ let layout = Layout::from_size_align_unchecked(len as usize, align);
+ let src = address as *mut u8;
+ let dst = alloc::alloc(layout);
+ copy_nonoverlapping(src, dst, len);
+ dst
+ }
+ } else {
+ null_mut()
+ }
+ }
+ _ => address as *mut u8,
+ };
+
+ let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
+ let old = if let Some(existing) = annotations.iter_mut().find(|e| e.id == id) {
+ let old = match existing.contents {
+ AnnotationContents::OwnedByteBuffer(len) => {
+ // If we owned the previous value of this annotation we must free it.
+ if (existing.address != 0) && (len > 0) {
+ let len = len as usize;
+ let align = min(usize::next_power_of_two(len), 32);
+ unsafe {
+ let layout = Layout::from_size_align_unchecked(len, align);
+ alloc::dealloc(existing.address as *mut u8, layout);
+ }
+ }
+ null_mut::<T>()
+ }
+ _ => existing.address as *mut T,
+ };
+
+ existing.contents = contents;
+ existing.address = address as usize;
+ old
+ } else {
+ annotations.push(Annotation {
+ id,
+ contents,
+ address: address as usize,
+ });
+ null_mut::<T>()
+ };
+
+ old
+}
+
+/// Register a pointer to an nsCString string.
+///
+/// Returns the value of the previously registered annotation or null.
///
/// This function will be exposed to C++
#[no_mangle]
-pub extern "C" fn mozannotation_register_nscstring(id: u32, address: *const nsCString) -> bool {
- let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
-
- if annotations.iter().any(|e| e.id == id) {
- return false;
- }
-
- annotations.push(Annotation {
- id,
- contents: AnnotationContents::NSCString,
- address: address as usize,
- });
-
- true
+pub extern "C" fn mozannotation_register_nscstring(
+ id: u32,
+ address: *const nsCString,
+) -> *const nsCString {
+ store_annotation(id, AnnotationContents::NSCStringPointer, address)
}
-/// Register an annotation containing a null-terminated string.
-/// Returns false if the annotation is already present (and doesn't change it).
+/// Create a copy of the provided string with a specified size that will be
+/// owned by the crate, and register a pointer to it.
///
/// This function will be exposed to C++
#[no_mangle]
-pub extern "C" fn mozannotation_register_cstring(
+pub extern "C" fn mozannotation_record_nscstring_from_raw_parts(
id: u32,
- address: *const *const std::ffi::c_char,
-) -> bool {
- let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
-
- if annotations.iter().any(|e| e.id == id) {
- return false;
- }
-
- annotations.push(Annotation {
+ address: *const u8,
+ size: usize,
+) {
+ store_annotation(
id,
- contents: AnnotationContents::CString,
- address: address as usize,
- });
-
- true
+ AnnotationContents::OwnedByteBuffer(size as u32),
+ address,
+ );
}
-/// Register an annotation pointing to a buffer holding a null-terminated string.
-/// Returns false if the annotation is already present (and doesn't change it).
+/// Register a pointer to a pointer to a nul-terminated string.
+///
+/// Returns the value of the previously registered annotation or null.
///
/// This function will be exposed to C++
#[no_mangle]
-pub extern "C" fn mozannotation_register_char_buffer(
+pub extern "C" fn mozannotation_register_cstring_ptr(
id: u32,
- address: *const std::ffi::c_char,
-) -> bool {
- let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
-
- if annotations.iter().any(|e| e.id == id) {
- return false;
- }
-
- annotations.push(Annotation {
- id,
- contents: AnnotationContents::CharBuffer,
- address: address as usize,
- });
-
- true
+ address: *const *const c_char,
+) -> *const *const c_char {
+ store_annotation(id, AnnotationContents::CStringPointer, address)
}
-/// Register an annotation pointing to a variable of type usize.
-/// Returns false if the annotation is already present (and doesn't change it).
+/// Register a pointer to a nul-terminated string.
+///
+/// Returns the value of the previously registered annotation or null.
///
/// This function will be exposed to C++
#[no_mangle]
-pub extern "C" fn mozannotation_register_usize(id: u32, address: *const usize) -> bool {
- let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
-
- if annotations.iter().any(|e| e.id == id) {
- return false;
- }
-
- annotations.push(Annotation {
- id,
- contents: AnnotationContents::USize,
- address: address as usize,
- });
+pub extern "C" fn mozannotation_register_cstring(id: u32, address: *const c_char) -> *const c_char {
+ store_annotation(id, AnnotationContents::CString, address)
+}
- true
+/// Create a copy of the provided nul-terminated string which will be owned by
+/// the crate, and register a pointer to it.
+///
+/// This function will be exposed to C++
+#[no_mangle]
+pub extern "C" fn mozannotation_record_cstring(id: u32, address: *const c_char) {
+ let len = unsafe { CStr::from_ptr(address).to_bytes().len() };
+ store_annotation(id, AnnotationContents::OwnedByteBuffer(len as u32), address);
}
-/// Register an annotation pointing to a fixed size buffer.
-/// Returns false if the annotation is already present (and doesn't change it).
+/// Register a pointer to a fixed size buffer.
+///
+/// Returns the value of the previously registered annotation or null.
///
/// This function will be exposed to C++
#[no_mangle]
@@ -321,34 +372,50 @@ pub extern "C" fn mozannotation_register_bytebuffer(
id: u32,
address: *const c_void,
size: u32,
-) -> bool {
- let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
-
- if annotations.iter().any(|e| e.id == id) {
- return false;
- }
+) -> *const c_void {
+ store_annotation(id, AnnotationContents::ByteBuffer(size), address)
+}
- annotations.push(Annotation {
- id,
- contents: AnnotationContents::ByteBuffer(size),
- address: address as usize,
- });
+/// Create a copy of the provided buffer which will be owned by the crate, and
+/// register a pointer to it.
+///
+/// This function will be exposed to C++
+#[no_mangle]
+pub extern "C" fn mozannotation_record_bytebuffer(id: u32, address: *const c_void, size: u32) {
+ store_annotation(id, AnnotationContents::OwnedByteBuffer(size), address);
+}
- true
+/// Unregister a crash annotation. Returns the previously registered pointer or
+/// null if none was present. Return null also if the crate owned the
+/// annotations' buffer.
+///
+/// This function will be exposed to C++
+#[no_mangle]
+pub extern "C" fn mozannotation_unregister(id: u32) -> *const c_void {
+ store_annotation(id, AnnotationContents::Empty, null_mut())
}
-/// Unregister a crash annotation. Returns false if the annotation is not present.
+/// Returns the raw address of an annotation if it has been registered or NULL
+/// if it hasn't.
///
/// This function will be exposed to C++
#[no_mangle]
-pub extern "C" fn mozannotation_unregister(id: u32) -> bool {
- let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
- let index = annotations.iter().position(|e| e.id == id);
+pub extern "C" fn mozannotation_get_contents(id: u32, contents: *mut AnnotationContents) -> usize {
+ let annotations = &MOZANNOTATIONS.lock().unwrap().data;
+ if let Some(annotation) = annotations.iter().find(|e| e.id == id) {
+ if annotation.contents == AnnotationContents::Empty {
+ return 0;
+ }
- if let Some(index) = index {
- annotations.remove(index);
- return true;
+ unsafe { *contents = annotation.contents };
+ return annotation.address;
}
- false
+ return 0;
+}
+
+#[no_mangle]
+pub extern "C" fn mozannotation_clear_all() {
+ let annotations = &mut MOZANNOTATIONS.lock().unwrap().data;
+ annotations.clear();
}
diff --git a/toolkit/crashreporter/mozannotation_server/Cargo.toml b/toolkit/crashreporter/mozannotation_server/Cargo.toml
index 747aff791e..3a5834a645 100644
--- a/toolkit/crashreporter/mozannotation_server/Cargo.toml
+++ b/toolkit/crashreporter/mozannotation_server/Cargo.toml
@@ -11,7 +11,6 @@ license = "MPL-2.0"
goblin = { version = "0.7", features = ["elf32", "elf64", "pe32", "pe64"] }
memoffset = "0.8"
mozannotation_client = { path = "../mozannotation_client/" }
-nsstring = { path = "../../../xpcom/rust/nsstring/" }
thin-vec = { version = "0.2.7", features = ["gecko-ffi"] }
thiserror = "1.0.38"
diff --git a/toolkit/crashreporter/mozannotation_server/src/lib.rs b/toolkit/crashreporter/mozannotation_server/src/lib.rs
index 4ecb8ec919..6ed5b3cc41 100644
--- a/toolkit/crashreporter/mozannotation_server/src/lib.rs
+++ b/toolkit/crashreporter/mozannotation_server/src/lib.rs
@@ -9,22 +9,21 @@ use crate::errors::*;
use process_reader::ProcessReader;
use mozannotation_client::{Annotation, AnnotationContents, AnnotationMutex};
-use nsstring::nsCString;
use std::cmp::min;
use std::iter::FromIterator;
-use std::mem::size_of;
+use std::mem::{size_of, ManuallyDrop};
use std::ptr::null_mut;
use thin_vec::ThinVec;
#[repr(C)]
+#[derive(Debug)]
pub enum AnnotationData {
Empty,
- UsizeData(usize),
- NSCStringData(nsCString),
ByteBuffer(ThinVec<u8>),
}
#[repr(C)]
+#[derive(Debug)]
pub struct CAnnotation {
id: u32,
data: AnnotationData,
@@ -100,33 +99,33 @@ pub fn retrieve_annotations(
// Read an annotation from the given address
fn read_annotation(reader: &ProcessReader, address: usize) -> Result<CAnnotation, ReadError> {
- let raw_annotation = reader.copy_object::<Annotation>(address)?;
+ let raw_annotation = ManuallyDrop::new(reader.copy_object::<Annotation>(address)?);
let mut annotation = CAnnotation {
id: raw_annotation.id,
data: AnnotationData::Empty,
};
+ if raw_annotation.address == 0 {
+ return Ok(annotation);
+ }
+
match raw_annotation.contents {
AnnotationContents::Empty => {}
- AnnotationContents::NSCString => {
+ AnnotationContents::NSCStringPointer => {
let string = copy_nscstring(reader, raw_annotation.address)?;
- annotation.data = AnnotationData::NSCStringData(string);
- }
- AnnotationContents::CString => {
- let string = copy_null_terminated_string_pointer(reader, raw_annotation.address)?;
- annotation.data = AnnotationData::NSCStringData(string);
+ annotation.data = AnnotationData::ByteBuffer(string);
}
- AnnotationContents::CharBuffer => {
- let string = copy_null_terminated_string(reader, raw_annotation.address)?;
- annotation.data = AnnotationData::NSCStringData(string);
+ AnnotationContents::CStringPointer => {
+ let buffer = copy_null_terminated_string_pointer(reader, raw_annotation.address)?;
+ annotation.data = AnnotationData::ByteBuffer(buffer);
}
- AnnotationContents::USize => {
- let value = reader.copy_object::<usize>(raw_annotation.address)?;
- annotation.data = AnnotationData::UsizeData(value);
+ AnnotationContents::CString => {
+ let buffer = copy_null_terminated_string(reader, raw_annotation.address)?;
+ annotation.data = AnnotationData::ByteBuffer(buffer);
}
- AnnotationContents::ByteBuffer(size) => {
- let value = copy_bytebuffer(reader, raw_annotation.address, size)?;
- annotation.data = AnnotationData::ByteBuffer(value);
+ AnnotationContents::ByteBuffer(size) | AnnotationContents::OwnedByteBuffer(size) => {
+ let buffer = copy_bytebuffer(reader, raw_annotation.address, size)?;
+ annotation.data = AnnotationData::ByteBuffer(buffer);
}
};
@@ -136,7 +135,7 @@ fn read_annotation(reader: &ProcessReader, address: usize) -> Result<CAnnotation
fn copy_null_terminated_string_pointer(
reader: &ProcessReader,
address: usize,
-) -> Result<nsCString, ReadError> {
+) -> Result<ThinVec<u8>, ReadError> {
let buffer_address = reader.copy_object::<usize>(address)?;
copy_null_terminated_string(reader, buffer_address)
}
@@ -144,7 +143,7 @@ fn copy_null_terminated_string_pointer(
fn copy_null_terminated_string(
reader: &ProcessReader,
address: usize,
-) -> Result<nsCString, ReadError> {
+) -> Result<ThinVec<u8>, ReadError> {
// Try copying the string word-by-word first, this is considerably faster
// than one byte at a time.
if let Ok(string) = copy_null_terminated_string_word_by_word(reader, address) {
@@ -155,7 +154,7 @@ fn copy_null_terminated_string(
// at a time. It's slow but it might work in situations where the string
// alignment causes word-by-word access to straddle page boundaries.
let mut length = 0;
- let mut string = Vec::<u8>::new();
+ let mut string = ThinVec::<u8>::new();
loop {
let char = reader.copy_object::<u8>(address + length)?;
@@ -167,33 +166,34 @@ fn copy_null_terminated_string(
}
}
- Ok(nsCString::from(&string[..length]))
+ Ok(string)
}
fn copy_null_terminated_string_word_by_word(
reader: &ProcessReader,
address: usize,
-) -> Result<nsCString, ReadError> {
+) -> Result<ThinVec<u8>, ReadError> {
const WORD_SIZE: usize = size_of::<usize>();
let mut length = 0;
- let mut string = Vec::<u8>::new();
+ let mut string = ThinVec::<u8>::new();
loop {
- let mut array = reader.copy_array::<u8>(address + length, WORD_SIZE)?;
+ let array = reader.copy_array::<u8>(address + length, WORD_SIZE)?;
let null_terminator = array.iter().position(|&e| e == 0);
length += null_terminator.unwrap_or(WORD_SIZE);
- string.append(&mut array);
+ string.extend(array.into_iter());
if null_terminator.is_some() {
+ string.truncate(length);
break;
}
}
- Ok(nsCString::from(&string[..length]))
+ Ok(string)
}
-fn copy_nscstring(reader: &ProcessReader, address: usize) -> Result<nsCString, ReadError> {
- // HACK: This assumes the layout of the string
+fn copy_nscstring(reader: &ProcessReader, address: usize) -> Result<ThinVec<u8>, ReadError> {
+ // HACK: This assumes the layout of the nsCString object
let length_address = address + size_of::<usize>();
let length = reader.copy_object::<u32>(length_address)?;
@@ -201,9 +201,9 @@ fn copy_nscstring(reader: &ProcessReader, address: usize) -> Result<nsCString, R
let data_address = reader.copy_object::<usize>(address)?;
reader
.copy_array::<u8>(data_address, length as _)
- .map(nsCString::from)
+ .map(ThinVec::from)
} else {
- Ok(nsCString::new())
+ Ok(ThinVec::<u8>::new())
}
}
diff --git a/toolkit/crashreporter/mozannotation_server/src/process_reader/linux.rs b/toolkit/crashreporter/mozannotation_server/src/process_reader/linux.rs
index db6dbd3df2..34f8ef90d5 100644
--- a/toolkit/crashreporter/mozannotation_server/src/process_reader/linux.rs
+++ b/toolkit/crashreporter/mozannotation_server/src/process_reader/linux.rs
@@ -261,8 +261,10 @@ enum PTraceOperation {
PeekData,
}
-#[cfg(target_os = "linux")]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
type PTraceOperationNative = libc::c_uint;
+#[cfg(all(target_os = "linux", target_env = "musl"))]
+type PTraceOperationNative = libc::c_int;
#[cfg(target_os = "android")]
type PTraceOperationNative = c_int;
diff --git a/toolkit/crashreporter/nsDummyExceptionHandler.cpp b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
index 7ccede695f..cd76630f3c 100644
--- a/toolkit/crashreporter/nsDummyExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsDummyExceptionHandler.cpp
@@ -4,10 +4,7 @@
* 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/. */
-#include <functional>
-
#include "nsExceptionHandler.h"
-#include "nsExceptionHandlerUtils.h"
namespace CrashReporter {
@@ -38,41 +35,71 @@ nsresult SetupExtraData(nsIFile* aAppDataDirectory,
nsresult UnsetExceptionHandler() { return NS_ERROR_NOT_IMPLEMENTED; }
-nsresult AnnotateCrashReport(Annotation key, bool data) {
- return NS_ERROR_NOT_IMPLEMENTED;
+const bool* RegisterAnnotationBool(Annotation aKey, const bool* aData) {
+ return nullptr;
}
-nsresult AnnotateCrashReport(Annotation key, int data) {
- return NS_ERROR_NOT_IMPLEMENTED;
+const uint32_t* RegisterAnnotationU32(Annotation aKey, const uint32_t* aData) {
+ return nullptr;
}
-nsresult AnnotateCrashReport(Annotation key, unsigned int data) {
- return NS_ERROR_NOT_IMPLEMENTED;
+const uint64_t* RegisterAnnotationU64(Annotation aKey, const uint64_t* aData) {
+ return nullptr;
}
-nsresult AnnotateCrashReport(Annotation key, const nsACString& data) {
- return NS_ERROR_NOT_IMPLEMENTED;
+const size_t* RegisterAnnotationUSize(Annotation aKey, const size_t* aData) {
+ return nullptr;
}
-nsresult AppendToCrashReportAnnotation(Annotation key, const nsACString& data) {
- return NS_ERROR_NOT_IMPLEMENTED;
+const char* RegisterAnnotationCString(Annotation aKey, const char* aData) {
+ return nullptr;
}
-nsresult RemoveCrashReportAnnotation(Annotation key) {
- return NS_ERROR_NOT_IMPLEMENTED;
+const nsCString* RegisterAnnotationNSCString(Annotation aKey,
+ const nsCString* aData) {
+ return nullptr;
+}
+
+nsresult RecordAnnotationBool(Annotation aKey, bool aData) {
+ return NS_ERROR_FAILURE;
+}
+
+nsresult RecordAnnotationU32(Annotation aKey, uint32_t aData) {
+ return NS_ERROR_FAILURE;
}
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, bool data) {}
+nsresult RecordAnnotationU64(Annotation aKey, uint64_t aData) {
+ return NS_ERROR_FAILURE;
+}
+
+nsresult RecordAnnotationUSize(Annotation aKey, size_t aData) {
+ return NS_ERROR_FAILURE;
+}
+
+nsresult RecordAnnotationCString(Annotation aKey, const char* aData) {
+ return NS_ERROR_FAILURE;
+}
+
+nsresult RecordAnnotationNSCString(Annotation aKey, const nsACString& aData) {
+ return NS_ERROR_FAILURE;
+}
+
+nsresult RecordAnnotationNSString(Annotation aKey, const nsAString& aData) {
+ return NS_ERROR_FAILURE;
+}
+
+nsresult UnrecordAnnotation(Annotation aKey) { return NS_ERROR_FAILURE; }
+
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key, bool data) {}
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, int data) {}
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key, int data) {}
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key,
- unsigned data) {}
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key, unsigned data) {}
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key,
- const nsACString& data) {}
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key,
+ const nsACString& data) {}
-AutoAnnotateCrashReport::~AutoAnnotateCrashReport() {}
+AutoRecordAnnotation::~AutoRecordAnnotation() {}
void MergeCrashAnnotations(AnnotationTable& aDst, const AnnotationTable& aSrc) {
}
diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp
index ceb021f7f3..aca266749a 100644
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -201,6 +201,7 @@ static const char kCrashMainID[] = "crash.main.3\n";
static google_breakpad::ExceptionHandler* gExceptionHandler = nullptr;
static mozilla::Atomic<bool> gEncounteredChildException(false);
+static nsCString gServerURL;
static xpstring pendingDirectory;
static xpstring crashReporterPath;
@@ -232,9 +233,7 @@ static const char* androidStartServiceCommand = nullptr;
#endif
// this holds additional data sent via the API
-static Mutex* crashReporterAPILock;
static Mutex* notesFieldLock;
-static AnnotationTable crashReporterAPIData_Table;
static nsCString* notesField = nullptr;
static bool isGarbageCollecting;
static uint32_t eventloopNestingLevel = 0;
@@ -656,11 +655,17 @@ class JSONAnnotationWriter : public AnnotationWriter {
size_t len = aLen ? aLen : my_strlen(aValue);
const char* annotationStr = AnnotationToString(aAnnotation);
- WritePrefix();
- mWriter.WriteBuffer(annotationStr, my_strlen(annotationStr));
- WriteSeparator();
- WriteEscapedString(aValue, len);
- WriteSuffix();
+ if (len && CrashReporter::ShouldIncludeAnnotation(aAnnotation, aValue)) {
+ WritePrefix();
+ mWriter.WriteBuffer(annotationStr, my_strlen(annotationStr));
+ WriteSeparator();
+ WriteEscapedString(aValue, len);
+ WriteSuffix();
+ }
+ };
+
+ void Write(Annotation aAnnotation, bool aValue) override {
+ Write(aAnnotation, aValue ? "1" : "0", 1);
};
void Write(Annotation aAnnotation, uint64_t aValue) override {
@@ -789,8 +794,10 @@ static void WritePHCAddrInfo(AnnotationWriter& writer,
break;
}
writer.Write(Annotation::PHCKind, kindString);
- writer.Write(Annotation::PHCBaseAddress, uintptr_t(aAddrInfo->mBaseAddr));
- writer.Write(Annotation::PHCUsableSize, aAddrInfo->mUsableSize);
+ writer.Write(Annotation::PHCBaseAddress,
+ reinterpret_cast<uint64_t>(aAddrInfo->mBaseAddr));
+ writer.Write(Annotation::PHCUsableSize,
+ static_cast<uint64_t>(aAddrInfo->mUsableSize));
WritePHCStackTrace(writer, Annotation::PHCAllocStack,
aAddrInfo->mAllocStack);
@@ -879,7 +886,8 @@ static void AnnotateMemoryStatus(AnnotationWriter& aWriter) {
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
if (GlobalMemoryStatusEx(&statex)) {
- aWriter.Write(Annotation::SystemMemoryUsePercentage, statex.dwMemoryLoad);
+ aWriter.Write(Annotation::SystemMemoryUsePercentage,
+ static_cast<uint64_t>(statex.dwMemoryLoad));
aWriter.Write(Annotation::TotalVirtualMemory, statex.ullTotalVirtual);
aWriter.Write(Annotation::AvailableVirtualMemory, statex.ullAvailVirtual);
aWriter.Write(Annotation::TotalPhysicalMemory, statex.ullTotalPhys);
@@ -888,9 +896,11 @@ static void AnnotateMemoryStatus(AnnotationWriter& aWriter) {
PERFORMANCE_INFORMATION info;
if (K32GetPerformanceInfo(&info, sizeof(info))) {
- aWriter.Write(Annotation::TotalPageFile, info.CommitLimit * info.PageSize);
+ aWriter.Write(Annotation::TotalPageFile,
+ static_cast<uint64_t>(info.CommitLimit * info.PageSize));
aWriter.Write(Annotation::AvailablePageFile,
- (info.CommitLimit - info.CommitTotal) * info.PageSize);
+ static_cast<uint64_t>((info.CommitLimit - info.CommitTotal) *
+ info.PageSize));
}
}
#elif XP_MACOSX
@@ -916,9 +926,9 @@ static void WriteAvailableMemoryStatus(AnnotationWriter& aWriter) {
if (host_statistics64(host, HOST_VM_INFO64, (host_info64_t)&stats, &count) ==
KERN_SUCCESS) {
aWriter.Write(Annotation::AvailablePhysicalMemory,
- stats.free_count * vm_page_size);
+ static_cast<uint64_t>(stats.free_count * vm_page_size));
aWriter.Write(Annotation::PurgeablePhysicalMemory,
- stats.purgeable_count * vm_page_size);
+ static_cast<uint64_t>(stats.purgeable_count * vm_page_size));
}
}
@@ -1199,7 +1209,8 @@ static void AnnotateMemoryStatus(AnnotationWriter& aWriter) {
pointOfInterest.dest->value = value;
}
if (pointOfInterest.annotation != Annotation::Count) {
- aWriter.Write(pointOfInterest.annotation, value);
+ aWriter.Write(pointOfInterest.annotation,
+ static_cast<uint64_t>(value));
}
}
break;
@@ -1224,7 +1235,8 @@ static void AnnotateMemoryStatus(AnnotationWriter& aWriter) {
}
if (memTotal.found && swapTotal.found) {
// If available, attempt to determine the available virtual memory.
- aWriter.Write(Annotation::TotalPageFile, memTotal.value + swapTotal.value);
+ aWriter.Write(Annotation::TotalPageFile,
+ static_cast<uint64_t>(memTotal.value + swapTotal.value));
}
}
@@ -1356,40 +1368,6 @@ static bool LaunchCrashHandlerService(const XP_CHAR* aProgramPath,
#endif
-static void WriteMainThreadRunnableName(AnnotationWriter& aWriter) {
-#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
- // Only try to collect this information if the main thread is crashing.
- if (!SignalSafeIsMainThread()) {
- return;
- }
-
- // NOTE: Use `my_memchr` over `strlen` to ensure we don't run off the end of
- // the buffer if it contains no null bytes. This is used instead of `strnlen`,
- // as breakpad's linux support library doesn't export a `my_strnlen` function.
- const char* buf = nsThread::sMainThreadRunnableName.begin();
- size_t len = nsThread::kRunnableNameBufSize;
- if (const void* end = my_memchr(buf, '\0', len)) {
- len = static_cast<const char*>(end) - buf;
- }
-
- if (len > 0) {
- aWriter.Write(Annotation::MainThreadRunnableName, buf, len);
- }
-#endif
-}
-
-static void WriteOOMAllocationSize(AnnotationWriter& aWriter) {
- if (gOOMAllocationSize) {
- aWriter.Write(Annotation::OOMAllocationSize, gOOMAllocationSize);
- }
-}
-
-static void WriteMozCrashReason(AnnotationWriter& aWriter) {
- if (gMozCrashReason != nullptr) {
- aWriter.Write(Annotation::MozCrashReason, gMozCrashReason);
- }
-}
-
static void WriteAnnotations(AnnotationWriter& aWriter,
const AnnotationTable& aAnnotations) {
for (auto key : MakeEnumeratedRange(Annotation::Count)) {
@@ -1408,13 +1386,65 @@ static void WriteAnnotationsForMainProcessCrash(PlatformWriter& pw,
const phc::AddrInfo* addrInfo,
time_t crashTime) {
JSONAnnotationWriter writer(pw);
- WriteAnnotations(writer, crashReporterAPIData_Table);
+
+ for (auto key : MakeEnumeratedRange(Annotation::Count)) {
+ AnnotationContents contents = {};
+ size_t address =
+ mozannotation_get_contents(static_cast<uint32_t>(key), &contents);
+ if (address != 0) {
+ switch (TypeOfAnnotation(key)) {
+ case AnnotationType::String:
+ switch (contents.tag) {
+ case AnnotationContents::Tag::NSCStringPointer: {
+ const nsCString* string =
+ reinterpret_cast<const nsCString*>(address);
+ writer.Write(key, string->Data(), string->Length());
+ } break;
+ case AnnotationContents::Tag::CStringPointer:
+ address = *(reinterpret_cast<size_t*>(address));
+ if (address == 0) {
+ break;
+ }
+ // FALLTHROUGH
+ case AnnotationContents::Tag::CString: {
+ writer.Write(key, reinterpret_cast<const char*>(address));
+ } break;
+ case AnnotationContents::Tag::ByteBuffer:
+ writer.Write(key, reinterpret_cast<const char*>(address),
+ static_cast<size_t>(contents.byte_buffer._0));
+ break;
+ case AnnotationContents::Tag::OwnedByteBuffer:
+ writer.Write(key, reinterpret_cast<const char*>(address),
+ static_cast<size_t>(contents.owned_byte_buffer._0));
+ break;
+ case AnnotationContents::Tag::Empty:
+ break;
+ }
+ break;
+ case AnnotationType::Boolean:
+ writer.Write(key, *reinterpret_cast<const bool*>(address));
+ break;
+ case AnnotationType::U32:
+ writer.Write(key, static_cast<uint64_t>(
+ *reinterpret_cast<uint32_t*>(address)));
+ break;
+ case AnnotationType::U64:
+ writer.Write(key, *reinterpret_cast<uint64_t*>(address));
+ break;
+ case AnnotationType::USize:
+ writer.Write(
+ key, static_cast<uint64_t>(*reinterpret_cast<size_t*>(address)));
+ break;
+ }
+ }
+ }
+
WriteSynthesizedAnnotations(writer);
writer.Write(Annotation::CrashTime, uint64_t(crashTime));
if (inactiveStateStart) {
writer.Write(Annotation::LastInteractionDuration,
- crashTime - inactiveStateStart);
+ static_cast<uint64_t>(crashTime - inactiveStateStart));
}
double uptimeTS = (TimeStamp::NowLoRes() - TimeStamp::ProcessCreation())
@@ -1427,34 +1457,14 @@ static void WriteAnnotationsForMainProcessCrash(PlatformWriter& pw,
if (lastCrashTime != 0) {
uint64_t timeSinceLastCrash = crashTime - lastCrashTime;
- if (timeSinceLastCrash != 0) {
- writer.Write(Annotation::SecondsSinceLastCrash, timeSinceLastCrash);
- }
- }
-
- if (isGarbageCollecting) {
- writer.Write(Annotation::IsGarbageCollecting, "1");
- }
-
- if (eventloopNestingLevel > 0) {
- writer.Write(Annotation::EventLoopNestingLevel, eventloopNestingLevel);
+ writer.Write(Annotation::SecondsSinceLastCrash, timeSinceLastCrash);
}
#if defined(XP_WIN) && defined(HAS_DLL_BLOCKLIST)
// HACK: The DLL blocklist code will manually write its annotations as JSON
- DllBlocklist_WriteNotes(writer);
+ DllBlocklist_WriteNotes();
#endif // defined(XP_WIN) && defined(HAS_DLL_BLOCKLIST)
- WriteMozCrashReason(writer);
-
- WriteMainThreadRunnableName(writer);
-
- WriteOOMAllocationSize(writer);
-
- if (gTexturesSize) {
- writer.Write(Annotation::TextureUsage, gTexturesSize);
- }
-
#ifdef MOZ_PHC
WritePHCAddrInfo(writer, addrInfo);
#endif
@@ -1889,19 +1899,50 @@ static nsresult LocateExecutable(nsIFile* aXREDirectory, const nsAString& aName,
#endif // !defined(MOZ_WIDGET_ANDROID)
-static void InitializeAnnotationFacilities() {
- crashReporterAPILock = new Mutex("crashReporterAPILock");
+static void InitializeAppNotes() {
notesFieldLock = new Mutex("notesFieldLock");
notesField = new nsCString();
}
-static void TeardownAnnotationFacilities() {
- std::fill(crashReporterAPIData_Table.begin(),
- crashReporterAPIData_Table.end(), ""_ns);
-
- delete crashReporterAPILock;
- crashReporterAPILock = nullptr;
+// Register crash annotations that are present in both main and child processes
+static void RegisterAnnotations() {
+ mozannotation_register_cstring_ptr(
+ static_cast<uint32_t>(Annotation::MozCrashReason), &gMozCrashReason);
+#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
+ mozannotation_register_cstring(
+ static_cast<uint32_t>(Annotation::MainThreadRunnableName),
+ &nsThread::sMainThreadRunnableName[0]);
+#endif
+ mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(Annotation::EventLoopNestingLevel),
+ &eventloopNestingLevel, sizeof(uint32_t));
+ mozannotation_register_nscstring(static_cast<uint32_t>(Annotation::Notes),
+ notesField);
+ mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(Annotation::OOMAllocationSize), &gOOMAllocationSize,
+ sizeof(size_t));
+ mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(Annotation::IsGarbageCollecting),
+ &isGarbageCollecting, sizeof(bool));
+ mozannotation_register_nscstring(static_cast<uint32_t>(Annotation::ServerURL),
+ &gServerURL);
+ mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(Annotation::TextureUsage), &gTexturesSize,
+ sizeof(size_t));
+#if defined(XP_WIN) && defined(HAS_DLL_BLOCKLIST)
+ mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(Annotation::BlocklistInitFailed),
+ DllBlocklist_GetBlocklistInitFailedPointer(), sizeof(bool));
+ mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(Annotation::User32BeforeBlocklist),
+ DllBlocklist_GetUser32BeforeBlocklistPointer(), sizeof(bool));
+ mozannotation_register_cstring(
+ static_cast<uint32_t>(Annotation::BlockedDllList),
+ DllBlocklist_GetBlocklistWriterData());
+#endif // defined(XP_WIN) && defined(HAS_DLL_BLOCKLIST)
+}
+static void TeardownAppNotes() {
delete notesFieldLock;
notesFieldLock = nullptr;
@@ -1929,7 +1970,8 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) {
doReport = ShouldReport();
RegisterRuntimeExceptionModule();
- InitializeAnnotationFacilities();
+ InitializeAppNotes();
+ RegisterAnnotations();
#if !defined(MOZ_WIDGET_ANDROID)
// Locate the crash reporter executable
@@ -2055,10 +2097,8 @@ nsresult SetExceptionHandler(nsIFile* aXREDirectory, bool force /*=false*/) {
#endif
// store application start time
- char timeString[32];
- time_t startupTime = time(nullptr);
- XP_TTOA(startupTime, timeString);
- AnnotateCrashReport(Annotation::StartupTime, nsDependentCString(timeString));
+ RecordAnnotationU64(Annotation::StartupTime,
+ static_cast<uint64_t>(time(nullptr)));
#if defined(XP_MACOSX)
// On OS X, many testers like to see the OS crash reporting dialog
@@ -2259,8 +2299,9 @@ nsresult SetupExtraData(nsIFile* aAppDataDirectory,
nsAutoCString data;
if (NS_SUCCEEDED(GetOrInit(dataDirectory, "InstallTime"_ns + aBuildID, data,
- InitInstallTime)))
- AnnotateCrashReport(Annotation::InstallTime, data);
+ InitInstallTime))) {
+ RecordAnnotationNSCString(Annotation::InstallTime, data);
+ }
// this is a little different, since we can't init it with anything,
// since it's stored at crash time, and we can't annotate the
@@ -2314,7 +2355,8 @@ nsresult UnsetExceptionHandler() {
delete gExceptionHandler;
- TeardownAnnotationFacilities();
+ gServerURL = "";
+ TeardownAppNotes();
if (!gExceptionHandler) return NS_ERROR_NOT_INITIALIZED;
@@ -2330,73 +2372,201 @@ nsresult UnsetExceptionHandler() {
return NS_OK;
}
-nsresult AnnotateCrashReport(Annotation key, bool data) {
- return AnnotateCrashReport(key, data ? "1"_ns : "0"_ns);
+const bool* RegisterAnnotationBool(Annotation aKey, const bool* aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::Boolean,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return nullptr;
+ }
+
+ return reinterpret_cast<const bool*>(mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(aKey), aData, sizeof(bool)));
}
-nsresult AnnotateCrashReport(Annotation key, int data) {
- nsAutoCString dataString;
- dataString.AppendInt(data);
+const uint32_t* RegisterAnnotationU32(Annotation aKey, const uint32_t* aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::U32,
+ "Wrong annotation type");
- return AnnotateCrashReport(key, dataString);
+ if (!GetEnabled()) {
+ return nullptr;
+ }
+
+ return reinterpret_cast<const uint32_t*>(mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(aKey), aData, sizeof(uint32_t)));
}
-nsresult AnnotateCrashReport(Annotation key, unsigned int data) {
- nsAutoCString dataString;
- dataString.AppendInt(data);
+const uint64_t* RegisterAnnotationU64(Annotation aKey, const uint64_t* aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::U64,
+ "Wrong annotation type");
- return AnnotateCrashReport(key, dataString);
+ if (!GetEnabled()) {
+ return nullptr;
+ }
+
+ return reinterpret_cast<const uint64_t*>(mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(aKey), aData, sizeof(uint64_t)));
}
-nsresult AnnotateCrashReport(Annotation key, const nsACString& data) {
- if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+const size_t* RegisterAnnotationUSize(Annotation aKey, const size_t* aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::USize,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return nullptr;
+ }
+
+ return reinterpret_cast<const size_t*>(mozannotation_register_bytebuffer(
+ static_cast<uint32_t>(aKey), aData, sizeof(size_t)));
+}
+
+const char* RegisterAnnotationCString(Annotation aKey, const char* aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::String,
+ "Wrong annotation type");
- MutexAutoLock lock(*crashReporterAPILock);
- crashReporterAPIData_Table[key] = data;
+ if (!GetEnabled()) {
+ return nullptr;
+ }
+ return mozannotation_register_cstring(static_cast<uint32_t>(aKey), aData);
+}
+
+const nsCString* RegisterAnnotationNSCString(Annotation aKey,
+ const nsCString* aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::String,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return nullptr;
+ }
+
+ return mozannotation_register_nscstring(static_cast<uint32_t>(aKey), aData);
+}
+
+nsresult RecordAnnotationBool(Annotation aKey, bool aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::Boolean,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ mozannotation_record_bytebuffer(static_cast<uint32_t>(aKey), &aData,
+ sizeof(bool));
return NS_OK;
}
-nsresult AppendToCrashReportAnnotation(Annotation key, const nsACString& data) {
- if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
+nsresult RecordAnnotationU32(Annotation aKey, uint32_t aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::U32,
+ "Wrong annotation type");
- MutexAutoLock lock(*crashReporterAPILock);
- nsAutoCString newString(crashReporterAPIData_Table[key]);
- newString.Append(" - "_ns);
- newString.Append(data);
- crashReporterAPIData_Table[key] = newString;
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ mozannotation_record_bytebuffer(static_cast<uint32_t>(aKey), &aData,
+ sizeof(uint32_t));
return NS_OK;
}
-nsresult RemoveCrashReportAnnotation(Annotation key) {
- return AnnotateCrashReport(key, ""_ns);
+nsresult RecordAnnotationU64(Annotation aKey, uint64_t aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::U64,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ mozannotation_record_bytebuffer(static_cast<uint64_t>(aKey), &aData,
+ sizeof(uint64_t));
+ return NS_OK;
}
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, bool data)
- : AutoAnnotateCrashReport(key, data ? "1"_ns : "0"_ns) {}
+nsresult RecordAnnotationUSize(Annotation aKey, size_t aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::USize,
+ "Wrong annotation type");
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, int data)
- : AutoAnnotateCrashReport(key, nsPrintfCString("%d", data)) {}
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key, unsigned data)
- : AutoAnnotateCrashReport(key, nsPrintfCString("%u", data)) {}
+ mozannotation_record_bytebuffer(static_cast<size_t>(aKey), &aData,
+ sizeof(size_t));
+ return NS_OK;
+}
-AutoAnnotateCrashReport::AutoAnnotateCrashReport(Annotation key,
- const nsACString& data)
- : mKey(key) {
+nsresult RecordAnnotationCString(Annotation aKey, const char* aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::String,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+ mozannotation_record_cstring(static_cast<uint32_t>(aKey), aData);
+ return NS_OK;
+}
+
+nsresult RecordAnnotationNSCString(Annotation aKey, const nsACString& aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::String,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ mozannotation_record_nscstring_from_raw_parts(
+ static_cast<uint32_t>(aKey),
+ reinterpret_cast<const uint8_t*>(aData.Data()), aData.Length());
+ return NS_OK;
+}
+
+nsresult RecordAnnotationNSString(Annotation aKey, const nsAString& aData) {
+ MOZ_ASSERT(TypeOfAnnotation(aKey) == AnnotationType::String,
+ "Wrong annotation type");
+
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ nsAutoCString data = NS_ConvertUTF16toUTF8(aData);
+ RecordAnnotationNSCString(aKey, data);
+ return NS_OK;
+}
+
+nsresult UnrecordAnnotation(Annotation aKey) {
+ if (!GetEnabled()) {
+ return NS_ERROR_NOT_INITIALIZED;
+ }
+
+ mozannotation_unregister(static_cast<uint32_t>(aKey));
+ return NS_OK;
+}
+
+// TODO: The first three methods here should be migrated to use native
+// types instead of turning the values into strings. They're not currently
+// used in mozilla-central so it doesn't really matter in the short term.
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key, bool data)
+ : AutoRecordAnnotation(key, data ? "1"_ns : "0"_ns) {}
+
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key, int data)
+ : AutoRecordAnnotation(key, nsPrintfCString("%d", data)) {}
+
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key, unsigned data)
+ : AutoRecordAnnotation(key, nsPrintfCString("%u", data)) {}
+
+AutoRecordAnnotation::AutoRecordAnnotation(Annotation key,
+ const nsACString& data)
+ : mKey(key), mCurrent(data) {
if (GetEnabled()) {
- MutexAutoLock lock(*crashReporterAPILock);
- auto& entry = crashReporterAPIData_Table[mKey];
- mPrevious = std::move(entry);
- entry = data;
+ mPrevious =
+ mozannotation_register_nscstring(static_cast<uint32_t>(key), &mCurrent);
}
}
-AutoAnnotateCrashReport::~AutoAnnotateCrashReport() {
+AutoRecordAnnotation::~AutoRecordAnnotation() {
if (GetEnabled()) {
- MutexAutoLock lock(*crashReporterAPILock);
- crashReporterAPIData_Table[mKey] = std::move(mPrevious);
+ Unused << mozannotation_register_nscstring(static_cast<uint32_t>(mKey),
+ mPrevious);
}
}
@@ -2409,11 +2579,6 @@ void MergeCrashAnnotations(AnnotationTable& aDst, const AnnotationTable& aSrc) {
}
}
-static void MergeContentCrashAnnotations(AnnotationTable& aDst) {
- MutexAutoLock lock(*crashReporterAPILock);
- MergeCrashAnnotations(aDst, crashReporterAPIData_Table);
-}
-
// Adds crash time, uptime and memory report annotations
static void AddCommonAnnotations(AnnotationTable& aAnnotations) {
const time_t crashTime = time(nullptr);
@@ -2461,23 +2626,8 @@ nsresult AppendAppNotesToCrashReport(const nsACString& data) {
if (!GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
MutexAutoLock lock(*notesFieldLock);
-
notesField->Append(data);
- return AnnotateCrashReport(Annotation::Notes, *notesField);
-}
-
-// Returns true if found, false if not found.
-static bool GetAnnotation(CrashReporter::Annotation key, nsACString& data) {
- if (!gExceptionHandler) return false;
-
- MutexAutoLock lock(*crashReporterAPILock);
- const nsCString& entry = crashReporterAPIData_Table[key];
- if (entry.IsEmpty()) {
- return false;
- }
-
- data = entry;
- return true;
+ return NS_OK;
}
nsresult RegisterAppMemory(void* ptr, size_t length) {
@@ -2513,15 +2663,19 @@ void SetIncludeContextHeap(bool aValue) {
}
bool GetServerURL(nsACString& aServerURL) {
- if (!gExceptionHandler) return false;
+ if (!gExceptionHandler) {
+ return false;
+ }
- return GetAnnotation(CrashReporter::Annotation::ServerURL, aServerURL);
+ aServerURL = gServerURL;
+ return true;
}
nsresult SetServerURL(const nsACString& aServerURL) {
- // store server URL with the API data
- // the client knows to handle this specially
- return AnnotateCrashReport(Annotation::ServerURL, aServerURL);
+ // Store the server URL as an annotation, the crash reporter client knows how
+ // to handle this specially.
+ gServerURL = aServerURL;
+ return NS_OK;
}
nsresult SetRestartArgs(int argc, char** argv) {
@@ -3107,12 +3261,89 @@ bool WriteExtraFile(const nsAString& id, const AnnotationTable& annotations) {
return WriteExtraFile(pw, annotations);
}
+template <typename T>
+static bool IsFixedSizeAnnotation(AnnotationContents& contents) {
+ return ((contents.tag == AnnotationContents::Tag::ByteBuffer) &&
+ (contents.byte_buffer._0 == sizeof(T))) ||
+ ((contents.tag == AnnotationContents::Tag::OwnedByteBuffer) &&
+ (contents.owned_byte_buffer._0 == sizeof(T)));
+}
+
// This adds annotations that were populated in the main process but are not
// present among the ones that were passed in. Additionally common annotations
// which are present in every crash report are added, including crash time,
// uptime, etc...
static void AddSharedAnnotations(AnnotationTable& aAnnotations) {
- MergeContentCrashAnnotations(aAnnotations);
+ for (auto key : MakeEnumeratedRange(Annotation::Count)) {
+ AnnotationContents contents = {};
+ nsAutoCString value;
+ size_t address =
+ mozannotation_get_contents(static_cast<uint32_t>(key), &contents);
+
+ if (address) {
+ switch (TypeOfAnnotation(key)) {
+ case AnnotationType::String:
+ switch (contents.tag) {
+ case AnnotationContents::Tag::Empty:
+ break;
+ case AnnotationContents::Tag::CStringPointer:
+ address = *reinterpret_cast<size_t*>(address);
+ if (address == 0) {
+ break;
+ }
+ // FALLTHROUGH
+ case AnnotationContents::Tag::CString:
+ value.Assign(reinterpret_cast<const char*>(address));
+ break;
+ case AnnotationContents::Tag::NSCStringPointer:
+ value.Assign(*reinterpret_cast<nsCString*>(address));
+ break;
+ case AnnotationContents::Tag::ByteBuffer:
+ value.Assign(reinterpret_cast<const char*>(address),
+ contents.byte_buffer._0);
+ break;
+ case AnnotationContents::Tag::OwnedByteBuffer:
+ value.Assign(reinterpret_cast<const char*>(address),
+ contents.owned_byte_buffer._0);
+ break;
+ }
+
+ break;
+ case AnnotationType::Boolean:
+ if (IsFixedSizeAnnotation<bool>(contents)) {
+ value.Assign(*reinterpret_cast<const bool*>(address) ? "1" : "0");
+ }
+ break;
+ case AnnotationType::U32:
+ if (IsFixedSizeAnnotation<uint32_t>(contents)) {
+ value.AppendInt(*reinterpret_cast<const uint32_t*>(address));
+ }
+ break;
+ case AnnotationType::U64:
+ if (IsFixedSizeAnnotation<uint64_t>(contents)) {
+ value.AppendInt(*reinterpret_cast<const uint64_t*>(address));
+ }
+ break;
+ case AnnotationType::USize:
+ if (IsFixedSizeAnnotation<size_t>(contents)) {
+#ifdef XP_MACOSX
+ // macOS defines size_t as unsigned long, which causes ambiguity
+ // when it comes to function overload, use a 64-bit integer instead
+ value.AppendInt(*reinterpret_cast<const uint64_t*>(address));
+#else
+ value.AppendInt(*reinterpret_cast<const size_t*>(address));
+#endif
+ }
+ break;
+ }
+
+ if (!value.IsEmpty() && aAnnotations[key].IsEmpty() &&
+ ShouldIncludeAnnotation(key, value.get())) {
+ aAnnotations[key] = value;
+ }
+ }
+ }
+
AddCommonAnnotations(aAnnotations);
}
@@ -3126,54 +3357,71 @@ static void AddChildProcessAnnotations(
}
for (const auto& annotation : *aChildAnnotations) {
- switch (annotation.data.tag) {
- case AnnotationData::Tag::Empty:
- break;
+ Annotation id = static_cast<Annotation>(annotation.id);
+ const AnnotationData& data = annotation.data;
- case AnnotationData::Tag::UsizeData:
- if (annotation.id ==
- static_cast<uint32_t>(Annotation::OOMAllocationSize)) {
- // We need to special-case OOMAllocationSize here because it should
- // not be added if its value is 0. We'll come up with a more general
- // method of skipping ignored values for crash annotations in the
- // follow-ups.
- if (annotation.data.usize_data._0 != 0) {
- aAnnotations[static_cast<Annotation>(annotation.id)] =
- nsPrintfCString("%zu", annotation.data.usize_data._0);
- }
- } else {
- aAnnotations[static_cast<Annotation>(annotation.id)] =
- nsPrintfCString("%zu", annotation.data.usize_data._0);
+ if ((id == Annotation::PHCBaseAddress) &&
+ (data.tag == AnnotationData::Tag::ByteBuffer)) {
+ // PHC is special for now, let's deal with it here
+#ifdef MOZ_PHC
+ const auto& buffer = data.byte_buffer._0;
+ mozilla::phc::AddrInfo addr_info;
+ memcpy(&addr_info, buffer.Elements(), sizeof(addr_info));
+ PopulatePHCAnnotations(aAnnotations, &addr_info);
+#endif
+ continue;
+ }
+
+ if (data.tag == AnnotationData::Tag::Empty) {
+ continue;
+ }
+
+ nsAutoCString value;
+ const uint8_t* buffer = data.byte_buffer._0.Elements();
+ const size_t length = data.byte_buffer._0.Length();
+
+ switch (TypeOfAnnotation(id)) {
+ case AnnotationType::String:
+ value.Assign(reinterpret_cast<const char*>(buffer), length);
+ break;
+ case AnnotationType::Boolean:
+ if (length == sizeof(bool)) {
+ value.Assign(*reinterpret_cast<const bool*>(buffer) ? "1" : "0");
}
break;
-
- case AnnotationData::Tag::NSCStringData: {
- const auto& string = annotation.data.nsc_string_data._0;
- if (!string.IsEmpty()) {
- aAnnotations[static_cast<Annotation>(annotation.id)] =
- annotation.data.nsc_string_data._0;
+ case AnnotationType::U32:
+ if (length == sizeof(uint32_t)) {
+ value.AppendInt(*reinterpret_cast<const uint32_t*>(buffer));
}
- } break;
-
- case AnnotationData::Tag::ByteBuffer: {
- if (annotation.id ==
- static_cast<uint32_t>(Annotation::PHCBaseAddress)) {
-#ifdef MOZ_PHC
- const auto& buffer = annotation.data.byte_buffer._0;
- mozilla::phc::AddrInfo addr_info;
- memcpy(&addr_info, buffer.Elements(), sizeof(addr_info));
- PopulatePHCAnnotations(aAnnotations, &addr_info);
+ break;
+ case AnnotationType::U64:
+ if (length == sizeof(uint64_t)) {
+ value.AppendInt(*reinterpret_cast<const uint64_t*>(buffer));
+ }
+ break;
+ case AnnotationType::USize:
+ if (length == sizeof(size_t)) {
+#ifdef XP_MACOSX
+ // macOS defines size_t as unsigned long, which causes ambiguity
+ // when it comes to function overload, use a 64-bit integer instead
+ value.AppendInt(*reinterpret_cast<const uint64_t*>(buffer));
+#else
+ value.AppendInt(*reinterpret_cast<const size_t*>(buffer));
#endif
}
- } break;
+ break;
+ }
+
+ if (!value.IsEmpty() && ShouldIncludeAnnotation(id, value.get())) {
+ aAnnotations[id] = value;
}
}
}
// It really only makes sense to call this function when
// ShouldReport() is true.
-// Uses dumpFile's filename to generate memoryReport's filename (same name with
-// a different extension)
+// Uses dumpFile's filename to generate memoryReport's filename (same name
+// with a different extension)
static bool MoveToPending(nsIFile* dumpFile, nsIFile* extraFile,
nsIFile* memoryReport) {
nsCOMPtr<nsIFile> pendingDir;
@@ -3480,44 +3728,15 @@ bool CreateNotificationPipeForChild(int* childCrashFd, int* childCrashRemapFd) {
bool SetRemoteExceptionHandler(const char* aCrashPipe) {
MOZ_ASSERT(!gExceptionHandler, "crash client already init'd");
RegisterRuntimeExceptionModule();
- InitializeAnnotationFacilities();
- for (auto key : MakeEnumeratedRange(Annotation::Count)) {
- switch (key) {
- case Annotation::MozCrashReason:
-#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
- case Annotation::MainThreadRunnableName:
-#endif
- case Annotation::OOMAllocationSize:
-#ifdef MOZ_PHC
- case Annotation::PHCBaseAddress:
-#endif
- break;
-
- default:
- mozannotation_register_nscstring(static_cast<uint32_t>(key),
- &crashReporterAPIData_Table[key]);
- }
- }
-
- mozannotation_register_cstring(
- static_cast<uint32_t>(Annotation::MozCrashReason), &gMozCrashReason);
-
-#ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY
- mozannotation_register_char_buffer(
- static_cast<uint32_t>(Annotation::MainThreadRunnableName),
- &nsThread::sMainThreadRunnableName[0]);
-#endif
-
- mozannotation_register_usize(
- static_cast<uint32_t>(Annotation::OOMAllocationSize),
- &gOOMAllocationSize);
+ InitializeAppNotes();
+ RegisterAnnotations();
#ifdef MOZ_PHC
// HACK: We're using the PHCBaseAddress annotation to point to the actual
// PHC address information object. This is because we currently have no
// difference between the internal representation of annotations and their
- // external representation. Once we remove the old annotation API this will
- // be properly addressed.
+ // external representation. Once we remove the old annotation API this
+ // will be properly addressed.
mozannotation_register_bytebuffer(
static_cast<uint32_t>(Annotation::PHCBaseAddress),
&mozilla::phc::gAddrInfo, sizeof(mozilla::phc::gAddrInfo));
@@ -3876,7 +4095,8 @@ bool UnsetRemoteExceptionHandler(bool wasSet) {
gExceptionHandler = nullptr;
}
#endif
- TeardownAnnotationFacilities();
+ gServerURL = "";
+ TeardownAppNotes();
return true;
}
@@ -3894,9 +4114,9 @@ void SetNotificationPipeForChild(int childCrashFd) {
// Bionic introduced support for getgrgid_r() and getgrnam_r() only in version
// 24 (that is Android Nougat / 7.1.2). Since GeckoView is built by version 16
// (32-bit) or 21 (64-bit), those functions aren't defined, but nix needs them
-// and minidump-writer relies on nix. These functions should never be called in
-// practice hence we implement them only to satisfy nix linking requirements but
-// we crash if we accidentally enter them.
+// and minidump-writer relies on nix. These functions should never be called
+// in practice hence we implement them only to satisfy nix linking
+// requirements but we crash if we accidentally enter them.
extern "C" {
diff --git a/toolkit/crashreporter/nsExceptionHandler.h b/toolkit/crashreporter/nsExceptionHandler.h
index f81cc07c8c..2564737137 100644
--- a/toolkit/crashreporter/nsExceptionHandler.h
+++ b/toolkit/crashreporter/nsExceptionHandler.h
@@ -18,12 +18,12 @@
#include "CrashAnnotations.h"
-#include <stddef.h>
-#include <stdint.h>
#include "nsError.h"
#include "nsString.h"
#include "nsXULAppAPI.h"
#include "prio.h"
+#include <stddef.h>
+#include <stdint.h>
#if defined(XP_WIN)
# ifdef WIN32_LEAN_AND_MEAN
@@ -95,30 +95,42 @@ nsresult SetMinidumpPath(const nsAString& aPath);
// child processes. Annotations added in the main process will be included in
// child process crashes too unless the child process sets its own annotations.
// If it does the child-provided annotation overrides the one set in the parent.
-nsresult AnnotateCrashReport(Annotation key, bool data);
-nsresult AnnotateCrashReport(Annotation key, int data);
-nsresult AnnotateCrashReport(Annotation key, unsigned int data);
-nsresult AnnotateCrashReport(Annotation key, const nsACString& data);
-nsresult AppendToCrashReportAnnotation(Annotation key, const nsACString& data);
-nsresult RemoveCrashReportAnnotation(Annotation key);
+const bool* RegisterAnnotationBool(Annotation aKey, const bool* aData);
+const uint32_t* RegisterAnnotationU32(Annotation aKey, const uint32_t* aData);
+const uint64_t* RegisterAnnotationU64(Annotation aKey, const uint64_t* aData);
+const size_t* RegisterAnnotationUSize(Annotation aKey, const size_t* aData);
+const char* RegisterAnnotationCString(Annotation aKey, const char* aData);
+const nsCString* RegisterAnnotationNSCString(Annotation aKey,
+ const nsCString* aData);
+
+nsresult RecordAnnotationBool(Annotation aKey, bool aData);
+nsresult RecordAnnotationU32(Annotation aKey, uint32_t aData);
+nsresult RecordAnnotationU64(Annotation aKey, uint64_t aData);
+nsresult RecordAnnotationUSize(Annotation aKey, size_t aData);
+nsresult RecordAnnotationCString(Annotation aKey, const char* aData);
+nsresult RecordAnnotationNSCString(Annotation aKey, const nsACString& aData);
+nsresult RecordAnnotationNSString(Annotation aKey, const nsAString& aData);
+nsresult UnrecordAnnotation(Annotation aKey);
+
nsresult AppendAppNotesToCrashReport(const nsACString& data);
// RAII class for setting a crash annotation during a limited scope of time.
// Will reset the named annotation to its previous value when destroyed.
//
-// This type's behavior is identical to that of AnnotateCrashReport().
-class MOZ_RAII AutoAnnotateCrashReport final {
+// This type's behavior is identical to that of RecordAnnotation().
+class MOZ_RAII AutoRecordAnnotation final {
public:
- AutoAnnotateCrashReport(Annotation key, bool data);
- AutoAnnotateCrashReport(Annotation key, int data);
- AutoAnnotateCrashReport(Annotation key, unsigned int data);
- AutoAnnotateCrashReport(Annotation key, const nsACString& data);
- ~AutoAnnotateCrashReport();
+ AutoRecordAnnotation(Annotation key, bool data);
+ AutoRecordAnnotation(Annotation key, int data);
+ AutoRecordAnnotation(Annotation key, unsigned int data);
+ AutoRecordAnnotation(Annotation key, const nsACString& data);
+ ~AutoRecordAnnotation();
#ifdef MOZ_CRASHREPORTER
private:
Annotation mKey;
- nsCString mPrevious;
+ const nsCString mCurrent;
+ const nsCString* mPrevious;
#endif
};
@@ -143,7 +155,8 @@ void GetAnnotation(uint32_t childPid, Annotation annotation,
nsACString& outStr);
// Functions for working with minidumps and .extras
-typedef mozilla::EnumeratedArray<Annotation, Annotation::Count, nsCString>
+typedef mozilla::EnumeratedArray<Annotation, nsCString,
+ size_t(Annotation::Count)>
AnnotationTable;
void DeleteMinidumpFilesForID(
const nsAString& aId,
diff --git a/toolkit/crashreporter/test/gtest/TestElfSoVersion.cpp b/toolkit/crashreporter/test/gtest/TestElfSoVersion.cpp
new file mode 100644
index 0000000000..a6c91a8dff
--- /dev/null
+++ b/toolkit/crashreporter/test/gtest/TestElfSoVersion.cpp
@@ -0,0 +1,143 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "gtest/gtest.h"
+#include "mozilla/SpinEventLoopUntil.h"
+
+#include "linux_utils.h"
+
+#define ASSERT_EQ_UNSIGNED(v, e) ASSERT_EQ((v), (uint32_t)(e))
+
+using namespace mozilla;
+
+class CrashReporter : public ::testing::Test {};
+
+TEST_F(CrashReporter, ElfSoNoVersion) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libdbus1.so", version);
+ ASSERT_TRUE(rv);
+}
+
+TEST_F(CrashReporter, ElfSo6) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libm.so.6", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 6);
+}
+
+TEST_F(CrashReporter, ElfSoNormalShort) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libdbus1.so.1.2", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 1);
+ ASSERT_EQ_UNSIGNED(version[1], 2);
+}
+
+TEST_F(CrashReporter, ElfSoNormalComplete) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libdbus1.so.1.2.3", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 1);
+ ASSERT_EQ_UNSIGNED(version[1], 2);
+ ASSERT_EQ_UNSIGNED(version[2], 3);
+}
+
+TEST_F(CrashReporter, ElfSoNormalPrerelease) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libdbus1.so.1.2.3.98", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 1);
+ ASSERT_EQ_UNSIGNED(version[1], 2);
+ ASSERT_EQ_UNSIGNED(version[2], 3);
+ ASSERT_EQ_UNSIGNED(version[3], 98);
+}
+
+TEST_F(CrashReporter, ElfSoNormalPrereleaseToomuch) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libdbus1.so.1.2.3.98.9.2.3", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 1);
+ ASSERT_EQ_UNSIGNED(version[1], 2);
+ ASSERT_EQ_UNSIGNED(version[2], 3);
+ ASSERT_EQ_UNSIGNED(version[3], 98);
+}
+
+TEST_F(CrashReporter, ElfSoBig) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libatk-1.0.so.0.25009.1", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 0);
+ ASSERT_EQ_UNSIGNED(version[1], 25009);
+ ASSERT_EQ_UNSIGNED(version[2], 1);
+}
+
+TEST_F(CrashReporter, ElfSoCairo) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libcairo.so.2.11800.3", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 2);
+ ASSERT_EQ_UNSIGNED(version[1], 11800);
+ ASSERT_EQ_UNSIGNED(version[2], 3);
+}
+
+TEST_F(CrashReporter, ElfSoMax) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion(
+ "libcairo.so.2147483647.2147483647.2147483647.2147483647", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], INT32_MAX);
+ ASSERT_EQ_UNSIGNED(version[1], INT32_MAX);
+ ASSERT_EQ_UNSIGNED(version[2], INT32_MAX);
+ ASSERT_EQ_UNSIGNED(version[3], INT32_MAX);
+}
+
+TEST_F(CrashReporter, ElfSoTimestamp) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libabsl_time_zone.so.20220623.0.0", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 20220623);
+ ASSERT_EQ_UNSIGNED(version[1], 0);
+ ASSERT_EQ_UNSIGNED(version[2], 0);
+}
+
+TEST_F(CrashReporter, ElfSoChars) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libabsl_time_zone.so.1.2.3rc4", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 1);
+ ASSERT_EQ_UNSIGNED(version[1], 2);
+ ASSERT_EQ_UNSIGNED(version[2], 34);
+}
+
+TEST_F(CrashReporter, ElfSoCharsMore) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libabsl_time_zone.so.1.2.3rc4.9", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 1);
+ ASSERT_EQ_UNSIGNED(version[1], 2);
+ ASSERT_EQ_UNSIGNED(version[2], 34);
+ ASSERT_EQ_UNSIGNED(version[3], 9);
+}
+
+TEST_F(CrashReporter, ElfSoCharsOnly) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion("libabsl_time_zone.so.final", version);
+ ASSERT_TRUE(rv);
+}
+
+TEST_F(CrashReporter, ElfSoNullVersion) {
+ bool rv = ElfFileSoVersion("libabsl_time_zone.so.1", nullptr);
+ ASSERT_FALSE(rv);
+}
+
+TEST_F(CrashReporter, ElfSoFullPath) {
+ uint32_t version[4] = {0, 0, 0, 0};
+ bool rv = ElfFileSoVersion(
+ "/usr/lib/x86_64-linux-gnu/libabsl_time_zone.so.20220623.0.0", version);
+ ASSERT_TRUE(rv);
+ ASSERT_EQ_UNSIGNED(version[0], 20220623);
+ ASSERT_EQ_UNSIGNED(version[1], 0);
+ ASSERT_EQ_UNSIGNED(version[2], 0);
+}
diff --git a/toolkit/crashreporter/test/gtest/moz.build b/toolkit/crashreporter/test/gtest/moz.build
new file mode 100644
index 0000000000..9aa1c0a0db
--- /dev/null
+++ b/toolkit/crashreporter/test/gtest/moz.build
@@ -0,0 +1,16 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+Library("crashreportertest")
+
+if CONFIG["OS_ARCH"] == "Linux":
+ UNIFIED_SOURCES = [
+ "TestElfSoVersion.cpp",
+ ]
+
+include("/ipc/chromium/chromium-config.mozbuild")
+
+FINAL_LIBRARY = "xul-gtest"
diff --git a/toolkit/crashreporter/test/moz.build b/toolkit/crashreporter/test/moz.build
index 1ebd9b9029..254d232e0e 100644
--- a/toolkit/crashreporter/test/moz.build
+++ b/toolkit/crashreporter/test/moz.build
@@ -9,6 +9,10 @@ XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.toml", "unit_ipc/xpcshell.toml"]
if CONFIG["MOZ_PHC"]:
XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell-phc.toml", "unit_ipc/xpcshell-phc.toml"]
+TEST_DIRS += [
+ "gtest",
+]
+
BROWSER_CHROME_MANIFESTS += ["browser/browser.toml"]
UNIFIED_SOURCES += [
diff --git a/toolkit/crashreporter/test/unit/head_crashreporter.js b/toolkit/crashreporter/test/unit/head_crashreporter.js
index c37c8acf8c..34602e2107 100644
--- a/toolkit/crashreporter/test/unit/head_crashreporter.js
+++ b/toolkit/crashreporter/test/unit/head_crashreporter.js
@@ -156,6 +156,9 @@ async function handleMinidump(callback) {
registerCleanupFunction(cleanup);
Assert.ok(extrafile.exists());
+ let data = await IOUtils.read(extrafile.path);
+ let decoder = new TextDecoder("ascii");
+ console.log("data = " + decoder.decode(data));
let extra = await IOUtils.readJSON(extrafile.path);
if (callback) {
diff --git a/toolkit/crashreporter/test/unit/test_crash_modules_linux.js b/toolkit/crashreporter/test/unit/test_crash_modules_linux.js
new file mode 100644
index 0000000000..9fcf587308
--- /dev/null
+++ b/toolkit/crashreporter/test/unit/test_crash_modules_linux.js
@@ -0,0 +1,33 @@
+add_task(async function run_test() {
+ if (!("@mozilla.org/toolkit/crash-reporter;1" in Cc)) {
+ dump(
+ "INFO | test_crash_modules.js | Can't test crashreporter in a non-libxul build.\n"
+ );
+ return;
+ }
+
+ await do_crash(
+ function () {
+ crashType = CrashTestUtils.CRASH_ABORT;
+ },
+ async function (mdump, extra, extraFile) {
+ runMinidumpAnalyzer(mdump);
+
+ // Refresh updated extra data
+ extra = await IOUtils.readJSON(extraFile.path);
+
+ // Check modules' versions
+ const modules = extra.StackTraces.modules;
+ const version_regexp = /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/;
+
+ for (let module of modules) {
+ console.debug("module", module);
+ console.debug("version => ", module.version);
+ console.debug("version regex => ", version_regexp.exec(module.version));
+ Assert.notEqual(version_regexp.exec(module.version), null);
+ }
+ },
+ // process will exit with a zero exit status
+ true
+ );
+});
diff --git a/toolkit/crashreporter/test/unit/xpcshell-phc.toml b/toolkit/crashreporter/test/unit/xpcshell-phc.toml
index 278cf28193..1bb182d852 100644
--- a/toolkit/crashreporter/test/unit/xpcshell-phc.toml
+++ b/toolkit/crashreporter/test/unit/xpcshell-phc.toml
@@ -1,8 +1,8 @@
[DEFAULT]
head = "head_crashreporter.js"
skip-if = [
- "toolkit == 'android'", # 1536217
- "os == 'win' && msix", # https://bugzilla.mozilla.org/show_bug.cgi?id=1807922
+ "os == 'android'", # 1536217
+ "win11_2009 && msix", # https://bugzilla.mozilla.org/show_bug.cgi?id=1807922
]
support-files = [
"crasher_subprocess_head.js",
diff --git a/toolkit/crashreporter/test/unit/xpcshell.toml b/toolkit/crashreporter/test/unit/xpcshell.toml
index ffa631d0a1..6b1676ac32 100644
--- a/toolkit/crashreporter/test/unit/xpcshell.toml
+++ b/toolkit/crashreporter/test/unit/xpcshell.toml
@@ -40,6 +40,10 @@ run-if = ["os == 'win'"]
reason = "Test covering Windows-specific module handling"
run-sequentially = "very high failure rate in parallel"
+["test_crash_modules_linux.js"]
+run-if = ["os == 'linux'"]
+reason = "Test covering Linux-specific module handling"
+
["test_crash_moz_crash.js"]
["test_crash_oom.js"]
@@ -51,7 +55,7 @@ run-sequentially = "very high failure rate in parallel"
["test_crash_rust_panic_multiline.js"]
["test_crash_stack_overflow.js"]
-skip-if = ["os != 'linux'"]
+run-if = ["os == 'linux'"]
reason = "Still broken on macOS and not yet supported on Windows"
["test_crash_terminator.js"]
@@ -60,71 +64,71 @@ reason = "Still broken on macOS and not yet supported on Windows"
["test_crash_win64cfi_alloc_large.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_alloc_small.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_epilog.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_infinite_code_chain.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
support-files = ["test_crash_win64cfi_infinite_code_chain.exe"]
["test_crash_win64cfi_infinite_entry_chain.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
support-files = ["test_crash_win64cfi_infinite_entry_chain.exe"]
["test_crash_win64cfi_invalid_exception_rva.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
support-files = ["test_crash_win64cfi_invalid_exception_rva.exe"]
["test_crash_win64cfi_not_a_pe.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
support-files = ["test_crash_win64cfi_not_a_pe.exe"]
["test_crash_win64cfi_push_nonvol.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_save_nonvol.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_save_nonvol_far.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_save_xmm128.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_save_xmm128_far.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_win64cfi_unknown_op.js"]
head = "head_crashreporter.js head_win64cfi.js"
-run-if = ["os == 'win' && bits == 64 && processor == 'x86_64'"]
+run-if = ["os == 'win' && bits == 64"]
reason = "Windows test specific to the x86-64 architecture"
["test_crash_with_memory_report.js"]
@@ -134,8 +138,10 @@ reason = "Windows test specific to the x86-64 architecture"
["test_crashreporter_appmem.js"]
# we need to skip this due to bug 838613
skip-if = [
- "os != 'win' && os != 'linux'",
- "os=='linux' && bits==32",
+ "os == 'android'",
+ "apple_silicon",
+ "apple_catalina",
+ "os == 'linux' && os_version == '18.04' && bits == 32",
]
["test_crashreporter_crash.js"]
@@ -149,4 +155,4 @@ run-sequentially = "very high failure rate in parallel"
run-sequentially = "very high failure rate in parallel"
["test_override_exception_handler.js"]
-skip-if = ["os != 'win'"]
+run-if = ["os == 'win'"]
diff --git a/toolkit/crashreporter/tools/symbolstore.py b/toolkit/crashreporter/tools/symbolstore.py
index bc16002503..8bc7a7120a 100755
--- a/toolkit/crashreporter/tools/symbolstore.py
+++ b/toolkit/crashreporter/tools/symbolstore.py
@@ -578,7 +578,7 @@ class Dumper:
# MODULE os cpu guid debug_file
(guid, debug_file) = (module_line.split())[3:5]
# strip off .pdb extensions, and append .sym
- sym_file = re.sub("\.pdb$", "", debug_file) + ".sym"
+ sym_file = re.sub(r"\.pdb$", "", debug_file) + ".sym"
# we do want forward slashes here
rel_path = os.path.join(debug_file, guid, sym_file).replace("\\", "/")
full_path = os.path.normpath(os.path.join(self.symbol_path, rel_path))