Flutter Engine
The Flutter Engine
unwinding_records.h
Go to the documentation of this file.
1// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4// Class for patching compiled code.
5
6#ifndef RUNTIME_PLATFORM_UNWINDING_RECORDS_H_
7#define RUNTIME_PLATFORM_UNWINDING_RECORDS_H_
8
10
11namespace dart {
12
14 public:
15 static intptr_t SizeInBytes();
16
17 static void RegisterExecutableMemory(void* start,
18 intptr_t size,
19 void** pp_dynamic_table);
20 static void UnregisterDynamicTable(void* p_dynamic_table);
21};
22
23#if (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS)) && \
24 defined(TARGET_ARCH_X64)
25
26#pragma pack(push, 1)
27//
28// Refer to https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64
29//
30typedef unsigned char UBYTE;
31typedef uint16_t USHORT;
32typedef union _UNWIND_CODE {
33 struct {
34 UBYTE CodeOffset;
35 UBYTE UnwindOp : 4;
36 UBYTE OpInfo : 4;
37 };
38 USHORT FrameOffset;
39} UNWIND_CODE, *PUNWIND_CODE;
40
41typedef struct _UNWIND_INFO {
42 UBYTE Version : 3;
43 UBYTE Flags : 5;
44 UBYTE SizeOfProlog;
45 UBYTE CountOfCodes;
46 UBYTE FrameRegister : 4;
47 UBYTE FrameOffset : 4;
48 UNWIND_CODE UnwindCode[2];
49} UNWIND_INFO, *PUNWIND_INFO;
50
51#if !defined(DART_HOST_OS_WINDOWS)
52typedef uint32_t ULONG;
53typedef struct _RUNTIME_FUNCTION {
54 ULONG BeginAddress;
55 ULONG EndAddress;
56 ULONG UnwindData;
57} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
58#endif
59
60static constexpr int kPushRbpInstructionLength = 1;
61static const int kMovRbpRspInstructionLength = 3;
62static constexpr int kRbpPrefixLength =
63 kPushRbpInstructionLength + kMovRbpRspInstructionLength;
64static constexpr int kRBP = 5;
65
66#ifndef UNW_FLAG_NHANDLER
67#define UNW_FLAG_NHANDLER 0
68#endif
69
70struct GeneratedCodeUnwindInfo {
71 UNWIND_INFO unwind_info;
72
73 GeneratedCodeUnwindInfo() {
74 unwind_info.Version = 1;
75 unwind_info.Flags = UNW_FLAG_NHANDLER;
76 unwind_info.SizeOfProlog = kRbpPrefixLength;
77 unwind_info.CountOfCodes = 2;
78 unwind_info.FrameRegister = kRBP;
79 unwind_info.FrameOffset = 0;
80 unwind_info.UnwindCode[0].CodeOffset = kRbpPrefixLength;
81 unwind_info.UnwindCode[0].UnwindOp = 3; // UWOP_SET_FPREG
82 unwind_info.UnwindCode[0].OpInfo = 0;
83 unwind_info.UnwindCode[1].CodeOffset = kPushRbpInstructionLength;
84 unwind_info.UnwindCode[1].UnwindOp = 0; // UWOP_PUSH_NONVOL
85 unwind_info.UnwindCode[1].OpInfo = kRBP;
86 }
87};
88
89static constexpr uint32_t kUnwindingRecordMagic = 0xAABBCCDD;
90
91struct CodeRangeUnwindingRecord {
92 void* dynamic_table;
93 uint32_t magic;
94 uint32_t runtime_function_count;
95 GeneratedCodeUnwindInfo unwind_info;
96 intptr_t exception_handler;
97 RUNTIME_FUNCTION runtime_function[1];
98};
99
100#pragma pack(pop)
101
102#elif defined(TARGET_ARCH_ARM64) && \
103 (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS))
104
105#pragma pack(push, 1)
106
107// ARM64 unwind codes are defined in below doc.
108// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
109enum UnwindOp8Bit {
110 OpNop = 0xE3,
111 OpAllocS = 0x00,
112 OpSaveFpLr = 0x40,
113 OpSaveFpLrX = 0x80,
114 OpSetFp = 0xE1,
115 OpAddFp = 0xE2,
116 OpEnd = 0xE4,
117};
118
119typedef uint32_t UNWIND_CODE;
120
121constexpr UNWIND_CODE Combine8BitUnwindCodes(uint8_t code0 = OpNop,
122 uint8_t code1 = OpNop,
123 uint8_t code2 = OpNop,
124 uint8_t code3 = OpNop) {
125 return static_cast<uint32_t>(code0) | (static_cast<uint32_t>(code1) << 8) |
126 (static_cast<uint32_t>(code2) << 16) |
127 (static_cast<uint32_t>(code3) << 24);
128}
129
130// UNWIND_INFO defines the static part (first 32-bit) of the .xdata record in
131// below doc.
132// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#xdata-records
133struct UNWIND_INFO {
134 uint32_t FunctionLength : 18;
135 uint32_t Version : 2;
136 uint32_t X : 1;
137 uint32_t E : 1;
138 uint32_t EpilogCount : 5;
139 uint32_t CodeWords : 5;
140};
141
142#if !defined(DART_HOST_OS_WINDOWS)
143typedef uint32_t ULONG;
144typedef uint32_t DWORD;
145typedef struct _RUNTIME_FUNCTION {
146 ULONG BeginAddress;
147 ULONG EndAddress;
148 ULONG UnwindData;
149} RUNTIME_FUNCTION, *PRUNTIME_FUNCTION;
150#endif
151
152/**
153 * Base on below doc, unwind record has 18 bits (unsigned) to encode function
154 * length, besides 2 LSB which are always 0.
155 * https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#xdata-records
156 */
157static const int kMaxFunctionLength = ((1 << 18) - 1) << 2;
158
159static constexpr int kDefaultNumberOfUnwindCodeWords = 1;
160static constexpr int kMaxExceptionThunkSize = 16;
161static constexpr int kFunctionLengthShiftSize = 2;
162static constexpr int kFunctionLengthMask = (1 << kFunctionLengthShiftSize) - 1;
163
164// Generate an unwind code for "stp fp, lr, [sp, #pre_index_offset]!".
165inline uint8_t MakeOpSaveFpLrX(int pre_index_offset) {
166 // See unwind code save_fplr_x in
167 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#unwind-codes
168 ASSERT(pre_index_offset <= -8);
169 ASSERT(pre_index_offset >= -512);
170 constexpr int kShiftSize = 3;
171 constexpr int kShiftMask = (1 << kShiftSize) - 1;
172 ASSERT((pre_index_offset & kShiftMask) == 0);
173 USE(kShiftMask);
174 // Solve for Z where -(Z+1)*8 = pre_index_offset.
175 int encoded_value = (-pre_index_offset >> kShiftSize) - 1;
176 return OpSaveFpLrX | encoded_value;
177}
178
179template <int kNumberOfUnwindCodeWords = kDefaultNumberOfUnwindCodeWords>
180struct UnwindData {
181 UNWIND_INFO unwind_info;
182 UNWIND_CODE unwind_codes[kNumberOfUnwindCodeWords];
183
184 UnwindData() {
185 memset(&unwind_info, 0, sizeof(UNWIND_INFO));
186 unwind_info.X = 0; // no exception handler
187 unwind_info.CodeWords = kNumberOfUnwindCodeWords;
188
189 // Generate unwind codes for the following prolog:
190 //
191 // stp fp, lr, [sp, #-kCallerSPOffset]!
192 // mov fp, sp
193 //
194 // This is a very rough approximation of the actual function prologs used in
195 // V8. In particular, we often push other data before the (fp, lr) pair,
196 // meaning the stack pointer computed for the caller frame is wrong. That
197 // error is acceptable when the unwinding info for the caller frame also
198 // depends on fp rather than sp, as is the case for V8 builtins and runtime-
199 // generated code.
200 static_assert(kNumberOfUnwindCodeWords >= 1);
201 uword kCallerSPOffset = -16;
202 unwind_codes[0] = Combine8BitUnwindCodes(
203 OpSetFp, MakeOpSaveFpLrX(kCallerSPOffset), OpEnd);
204
205 // Fill the rest with nops.
206 for (int i = 1; i < kNumberOfUnwindCodeWords; ++i) {
207 unwind_codes[i] = Combine8BitUnwindCodes();
208 }
209 }
210};
211
212static const uint32_t kDefaultRuntimeFunctionCount = 1;
213static constexpr uint32_t kUnwindingRecordMagic = 0xAABBCCEE;
214
215struct CodeRangeUnwindingRecord {
216 void* dynamic_table;
217 uint32_t magic;
218 uint32_t runtime_function_count;
219 UnwindData<> unwind_info;
220 uint32_t exception_handler;
221
222 // For Windows ARM64 unwinding, register 2 unwind_info for each code range,
223 // unwind_info for all full size ranges (1MB - 4 bytes) and unwind_info1 for
224 // the remaining non full size range. There is at most 1 range which is less
225 // than full size.
226 UnwindData<> unwind_info1;
227
228 // More RUNTIME_FUNCTION structs could follow below array because the number
229 // of RUNTIME_FUNCTION needed to cover given code range is computed at
230 // runtime.
231 RUNTIME_FUNCTION runtime_function[kDefaultRuntimeFunctionCount];
232};
233
234#pragma pack(pop)
235
236#endif // (defined(DART_TARGET_OS_WINDOWS) || defined(DART_HOST_OS_WINDOWS))
237
238} // namespace dart
239
240#endif // RUNTIME_PLATFORM_UNWINDING_RECORDS_H_
Version
static const SkScalar X
Definition: StrokeBench.cpp:54
static void RegisterExecutableMemory(void *start, intptr_t size, void **pp_dynamic_table)
static void UnregisterDynamicTable(void *p_dynamic_table)
#define ASSERT(E)
Definition: dart_vm.cc:33
uintptr_t uword
Definition: globals.h:501
static void USE(T &&)
Definition: globals.h:618
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
DWORD ULONG
Definition: windows_types.h:40
unsigned long DWORD
Definition: windows_types.h:22