Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
immediate_crash.h
Go to the documentation of this file.
1// Copyright 2024 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CORE_FXCRT_IMMEDIATE_CRASH_H_
6#define CORE_FXCRT_IMMEDIATE_CRASH_H_
7
8#include "build/build_config.h"
9
10// Crashes in the fastest possible way with no attempt at logging.
11// There are several constraints; see http://crbug.com/664209 for more context.
12//
13// - TRAP_SEQUENCE_() must be fatal. It should not be possible to ignore the
14// resulting exception or simply hit 'continue' to skip over it in a debugger.
15// - Different instances of TRAP_SEQUENCE_() must not be folded together, to
16// ensure crash reports are debuggable. Unlike __builtin_trap(), asm volatile
17// blocks will not be folded together.
18// Note: TRAP_SEQUENCE_() previously required an instruction with a unique
19// nonce since unlike clang, GCC folds together identical asm volatile
20// blocks.
21// - TRAP_SEQUENCE_() must produce a signal that is distinct from an invalid
22// memory access.
23// - TRAP_SEQUENCE_() must be treated as a set of noreturn instructions.
24// __builtin_unreachable() is used to provide that hint here. clang also uses
25// this as a heuristic to pack the instructions in the function epilogue to
26// improve code density.
27//
28// Additional properties that are nice to have:
29// - TRAP_SEQUENCE_() should be as compact as possible.
30// - The first instruction of TRAP_SEQUENCE_() should not change, to avoid
31// shifting crash reporting clusters. As a consequence of this, explicit
32// assembly is preferred over intrinsics.
33// Note: this last bullet point may no longer be true, and may be removed in
34// the future.
35
36// Note: TRAP_SEQUENCE Is currently split into two macro helpers due to the fact
37// that clang emits an actual instruction for __builtin_unreachable() on certain
38// platforms (see https://crbug.com/958675). In addition, the int3/bkpt/brk will
39// be removed in followups, so splitting it up like this now makes it easy to
40// land the followups.
41
42#if defined(COMPILER_GCC)
43
44#if BUILDFLAG(IS_NACL)
45
46// Crash report accuracy is not guaranteed on NaCl.
47#define TRAP_SEQUENCE1_() __builtin_trap()
48#define TRAP_SEQUENCE2_() asm volatile("")
49
50#elif defined(ARCH_CPU_X86_FAMILY)
51
52// TODO(https://crbug.com/958675): In theory, it should be possible to use just
53// int3. However, there are a number of crashes with SIGILL as the exception
54// code, so it seems likely that there's a signal handler that allows execution
55// to continue after SIGTRAP.
56#define TRAP_SEQUENCE1_() asm volatile("int3")
57
58#if BUILDFLAG(IS_APPLE)
59// Intentionally empty: __builtin_unreachable() is always part of the sequence
60// (see IMMEDIATE_CRASH below) and already emits a ud2 on Mac.
61#define TRAP_SEQUENCE2_() asm volatile("")
62#else
63#define TRAP_SEQUENCE2_() asm volatile("ud2")
64#endif // BUILDFLAG(IS_APPLE)
65
66#elif defined(ARCH_CPU_ARMEL)
67
68// bkpt will generate a SIGBUS when running on armv7 and a SIGTRAP when running
69// as a 32 bit userspace app on arm64. There doesn't seem to be any way to
70// cause a SIGTRAP from userspace without using a syscall (which would be a
71// problem for sandboxing).
72// TODO(https://crbug.com/958675): Remove bkpt from this sequence.
73#define TRAP_SEQUENCE1_() asm volatile("bkpt #0")
74#define TRAP_SEQUENCE2_() asm volatile("udf #0")
75
76#elif defined(ARCH_CPU_ARM64)
77
78// This will always generate a SIGTRAP on arm64.
79// TODO(https://crbug.com/958675): Remove brk from this sequence.
80#define TRAP_SEQUENCE1_() asm volatile("brk #0")
81#define TRAP_SEQUENCE2_() asm volatile("hlt #0")
82
83#else
84
85// Crash report accuracy will not be guaranteed on other architectures, but at
86// least this will crash as expected.
87#define TRAP_SEQUENCE1_() __builtin_trap()
88#define TRAP_SEQUENCE2_() asm volatile("")
89
90#endif // ARCH_CPU_*
91
92#elif defined(COMPILER_MSVC)
93
94#if !defined(__clang__)
95
96// MSVC x64 doesn't support inline asm, so use the MSVC intrinsic.
97#define TRAP_SEQUENCE1_() __debugbreak()
98#define TRAP_SEQUENCE2_()
99
100#elif defined(ARCH_CPU_ARM64)
101
102// Windows ARM64 uses "BRK #F000" as its breakpoint instruction, and
103// __debugbreak() generates that in both VC++ and clang.
104#define TRAP_SEQUENCE1_() __debugbreak()
105// Intentionally empty: __builtin_unreachable() is always part of the sequence
106// (see IMMEDIATE_CRASH below) and already emits a ud2 on Win64,
107// https://crbug.com/958373
108#define TRAP_SEQUENCE2_() __asm volatile("")
109
110#else
111
112#define TRAP_SEQUENCE1_() asm volatile("int3")
113#define TRAP_SEQUENCE2_() asm volatile("ud2")
114
115#endif // __clang__
116
117#else
118
119#error No supported trap sequence!
120
121#endif // COMPILER_GCC
122
123#define TRAP_SEQUENCE_()
124 do {
125 TRAP_SEQUENCE1_();
126 TRAP_SEQUENCE2_();
127 } while (false)
128
129// This version of ALWAYS_INLINE inlines even in is_debug=true.
130// TODO(pbos): See if NDEBUG can be dropped from ALWAYS_INLINE as well, and if
131// so merge. Otherwise document why it cannot inline in debug in
132// base/compiler_specific.h.
133#if defined(COMPILER_GCC)
134#define IMMEDIATE_CRASH_ALWAYS_INLINE inline __attribute__((__always_inline__))
135#elif defined(COMPILER_MSVC)
136#define IMMEDIATE_CRASH_ALWAYS_INLINE __forceinline
137#else
138#define IMMEDIATE_CRASH_ALWAYS_INLINE inline
139#endif
140
141namespace pdfium {
142
145#if defined(__clang__) || defined(COMPILER_GCC)
146 __builtin_unreachable();
147#endif // defined(__clang__) || defined(COMPILER_GCC)
148}
149
150} // namespace pdfium
151
152#endif // CORE_FXCRT_IMMEDIATE_CRASH_H_
T & reference
Definition span.h:195
constexpr span(T(&array)[N]) noexcept
Definition span.h:211
constexpr reverse_iterator rend() const noexcept
Definition span.h:348
span last() const
Definition span.h:283
constexpr reverse_iterator rbegin() const noexcept
Definition span.h:345
T * iterator
Definition span.h:196
constexpr const_reverse_iterator crend() const noexcept
Definition span.h:355
span first() const
Definition span.h:269
std::reverse_iterator< iterator > reverse_iterator
Definition span.h:198
const span first(size_t count) const
Definition span.h:276
typename std::remove_cv< T >::type value_type
Definition span.h:193
span & operator=(const span &other) noexcept
Definition span.h:258
constexpr const_iterator cbegin() const noexcept
Definition span.h:342
constexpr const_iterator cend() const noexcept
Definition span.h:343
constexpr const_reverse_iterator crbegin() const noexcept
Definition span.h:352
const span last(size_t count) const
Definition span.h:290
constexpr bool empty() const noexcept
Definition span.h:316
constexpr size_t size() const noexcept
Definition span.h:314
constexpr span(Container &container)
Definition span.h:238
friend constexpr span< U > make_span(U *data, size_t size) noexcept
span subspan() const
Definition span.h:297
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition span.h:199
const span subspan(size_t pos, size_t count=dynamic_extent) const
Definition span.h:305
constexpr iterator begin() const noexcept
Definition span.h:337
constexpr size_t size_bytes() const noexcept
Definition span.h:315
constexpr span() noexcept=default
span(const Container &container)
Definition span.h:245
constexpr span(std::array< T, N > &array) noexcept
Definition span.h:216
T * pointer
Definition span.h:194
constexpr T & back() const noexcept
Definition span.h:329
constexpr span(const std::array< std::remove_cv_t< T >, N > &array) noexcept
Definition span.h:221
constexpr T * data() const noexcept
Definition span.h:334
constexpr T & front() const noexcept
Definition span.h:324
constexpr span(const span &other) noexcept=default
UNSAFE_BUFFER_USAGE constexpr span(T *data, size_t size) noexcept
Definition span.h:204
constexpr span(const span< U, M, R > &other)
Definition span.h:255
T & operator[](size_t index) const noexcept
Definition span.h:319
constexpr iterator end() const noexcept
Definition span.h:338
const T * const_iterator
Definition span.h:197
~span() noexcept=default
#define UNSAFE_BUFFERS(...)
#define GSL_POINTER
#define TRIVIAL_ABI
#define UNLIKELY(x)
#define HAS_ATTRIBUTE(x)
#define UNSAFE_BUFFER_USAGE
void CRYPT_MD5Finish(CRYPT_md5_context *context, pdfium::span< uint8_t, 16 > digest)
Definition fx_crypt.cpp:203
#define P(a, b, c, d, k, s, t)
void CRYPT_MD5Generate(pdfium::span< const uint8_t > data, pdfium::span< uint8_t, 16 > digest)
Definition fx_crypt.cpp:219
#define S(x, n)
void CRYPT_ArcFourCryptBlock(pdfium::span< uint8_t > data, pdfium::span< const uint8_t > key)
Definition fx_crypt.cpp:157
void CRYPT_ArcFourSetup(CRYPT_rc4_context *context, pdfium::span< const uint8_t > key)
Definition fx_crypt.cpp:131
void CRYPT_MD5Update(CRYPT_md5_context *context, pdfium::span< const uint8_t > data)
Definition fx_crypt.cpp:175
void CRYPT_ArcFourCrypt(CRYPT_rc4_context *context, pdfium::span< uint8_t > data)
Definition fx_crypt.cpp:146
CRYPT_md5_context CRYPT_MD5Start()
Definition fx_crypt.cpp:164
void CRYPT_AESEncrypt(CRYPT_aes_context *ctx, pdfium::span< uint8_t > dest, pdfium::span< const uint8_t > src)
void CRYPT_AESSetIV(CRYPT_aes_context *ctx, const uint8_t *iv)
void CRYPT_AESDecrypt(CRYPT_aes_context *ctx, uint8_t *dest, const uint8_t *src, uint32_t size)
void CRYPT_AESSetKey(CRYPT_aes_context *ctx, const uint8_t *key, uint32_t keylen)
#define IMMEDIATE_CRASH_ALWAYS_INLINE
#define TRAP_SEQUENCE_()
std::is_integral< decltype(std::declval< Container >().size())> ContainerHasIntegralSize
Definition span.h:63
IsSpanImpl< typename std::decay< T >::type > IsSpan
Definition span.h:43
std::is_convertible< From *, To * > IsLegalSpanConversion
Definition span.h:55
IsStdArrayImpl< typename std::decay< T >::type > IsStdArray
Definition span.h:52
constexpr span< T > make_span(T(&array)[N]) noexcept
Definition span.h:374
span< char > as_writable_chars(span< T, N, P > s) noexcept
Definition span.h:427
span< const uint8_t > as_bytes(span< T, N, P > s) noexcept
Definition span.h:400
constexpr size_t dynamic_extent
Definition span.h:24
static constexpr span< T > span_from_ref(T &single_object) noexcept
Definition span.h:437
static constexpr span< const uint8_t > byte_span_from_ref(const T &single_object) noexcept
Definition span.h:446
UNSAFE_BUFFER_USAGE constexpr span< T > make_span(T *data, size_t size) noexcept
Definition span.h:369
span< const uint8_t > as_byte_span(T &&arg)
Definition span.h:465
span< const char > as_chars(span< T, N, P > s) noexcept
Definition span.h:417
span< const uint8_t > as_byte_span(const T &arg)
Definition span.h:461
UNOWNED_PTR_EXCLUSION T * DefaultSpanInternalPtr
Definition span.h:27
span< uint8_t > as_writable_bytes(span< T, N, P > s) noexcept
Definition span.h:410
constexpr span< T > make_span(std::array< T, N > &array) noexcept
Definition span.h:379
constexpr span< T > make_span(Container &container)
Definition span.h:386
constexpr span< uint8_t > as_writable_byte_span(T &&arg)
Definition span.h:475
IMMEDIATE_CRASH_ALWAYS_INLINE void ImmediateCrash()
static constexpr span< uint8_t > byte_span_from_ref(T &single_object) noexcept
Definition span.h:451
constexpr span< T > make_span(const Container &container)
Definition span.h:394
#define CHECK(cvref)
#define assert
#define __has_attribute(x)
std::array< uint32_t, kMaxNb > iv
std::array< uint32_t, kSchedSize > invkeysched
static constexpr int kMaxNr
static constexpr int kSchedSize
static constexpr int kMaxNb
std::array< uint32_t, kSchedSize > keysched
uint8_t buffer[64]
Definition fx_crypt.h:28
std::array< uint32_t, 4 > state
Definition fx_crypt.h:27
std::array< uint32_t, 2 > total
Definition fx_crypt.h:26
std::array< int32_t, kPermutationLength > m
Definition fx_crypt.h:22
static constexpr int32_t kPermutationLength
Definition fx_crypt.h:18
#define UNOWNED_PTR_EXCLUSION