| // Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 | // Class for patching compiled code. | 
 |  | 
 | #ifndef RUNTIME_PLATFORM_UNWINDING_RECORDS_H_ | 
 | #define RUNTIME_PLATFORM_UNWINDING_RECORDS_H_ | 
 |  | 
 | #include "platform/allocation.h" | 
 |  | 
 | namespace dart { | 
 |  | 
 | class UnwindingRecordsPlatform : public AllStatic { | 
 |  public: | 
 |   static void Init(); | 
 |   static void Cleanup(); | 
 |  | 
 |   static intptr_t SizeInBytes(); | 
 |  | 
 |   static void RegisterExecutableMemory(void* start, | 
 |                                        intptr_t size, | 
 |                                        void** pp_dynamic_table); | 
 |   static void UnregisterDynamicTable(void* p_dynamic_table); | 
 |  | 
 |   static void* GetAddGrowableFunctionTableFunc(); | 
 |   static void* GetDeleteGrowableFunctionTableFunc(); | 
 | }; | 
 |  | 
 | #if defined(DART_HOST_OS_WINDOWS) && defined(TARGET_ARCH_X64) | 
 |  | 
 | #pragma pack(push, 1) | 
 | // | 
 | // Refer to https://learn.microsoft.com/en-us/cpp/build/exception-handling-x64 | 
 | // | 
 | typedef unsigned char UBYTE; | 
 | typedef union _UNWIND_CODE { | 
 |   struct { | 
 |     UBYTE CodeOffset; | 
 |     UBYTE UnwindOp : 4; | 
 |     UBYTE OpInfo : 4; | 
 |   }; | 
 |   USHORT FrameOffset; | 
 | } UNWIND_CODE, *PUNWIND_CODE; | 
 |  | 
 | typedef struct _UNWIND_INFO { | 
 |   UBYTE Version : 3; | 
 |   UBYTE Flags : 5; | 
 |   UBYTE SizeOfProlog; | 
 |   UBYTE CountOfCodes; | 
 |   UBYTE FrameRegister : 4; | 
 |   UBYTE FrameOffset : 4; | 
 |   UNWIND_CODE UnwindCode[2]; | 
 | } UNWIND_INFO, *PUNWIND_INFO; | 
 |  | 
 | static constexpr int kPushRbpInstructionLength = 1; | 
 | static const int kMovRbpRspInstructionLength = 3; | 
 | static constexpr int kRbpPrefixLength = | 
 |     kPushRbpInstructionLength + kMovRbpRspInstructionLength; | 
 | static constexpr int kRBP = 5; | 
 |  | 
 | struct GeneratedCodeUnwindInfo { | 
 |   UNWIND_INFO unwind_info; | 
 |  | 
 |   GeneratedCodeUnwindInfo() { | 
 |     unwind_info.Version = 1; | 
 |     unwind_info.Flags = UNW_FLAG_NHANDLER; | 
 |     unwind_info.SizeOfProlog = kRbpPrefixLength; | 
 |     unwind_info.CountOfCodes = 2; | 
 |     unwind_info.FrameRegister = kRBP; | 
 |     unwind_info.FrameOffset = 0; | 
 |     unwind_info.UnwindCode[0].CodeOffset = kRbpPrefixLength; | 
 |     unwind_info.UnwindCode[0].UnwindOp = 3;  // UWOP_SET_FPREG | 
 |     unwind_info.UnwindCode[0].OpInfo = 0; | 
 |     unwind_info.UnwindCode[1].CodeOffset = kPushRbpInstructionLength; | 
 |     unwind_info.UnwindCode[1].UnwindOp = 0;  // UWOP_PUSH_NONVOL | 
 |     unwind_info.UnwindCode[1].OpInfo = kRBP; | 
 |   } | 
 | }; | 
 |  | 
 | struct CodeRangeUnwindingRecord { | 
 |   void* dynamic_table; | 
 |   uint32_t runtime_function_count; | 
 |   GeneratedCodeUnwindInfo unwind_info; | 
 |   intptr_t exception_handler; | 
 |   RUNTIME_FUNCTION runtime_function[1]; | 
 | }; | 
 |  | 
 | #pragma pack(pop) | 
 |  | 
 | #endif  // defined(DART_HOST_OS_WINDOWS) && defined(TARGET_ARCH_X64) | 
 |  | 
 | }  // namespace dart | 
 |  | 
 | #endif  // RUNTIME_PLATFORM_UNWINDING_RECORDS_H_ |