| //------------------------------------------------------------------------------------------------------- |
| // Copyright (C) Microsoft. All rights reserved. |
| // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. |
| //------------------------------------------------------------------------------------------------------- |
| #include "Backend.h" |
| |
| // Conditionally-compiled on x64 and arm/arm64 |
| #if PDATA_ENABLED |
| |
| #ifdef _WIN32 |
| // ---------------------------------------------------------------------------- |
| // _WIN32 x64 unwind uses PDATA |
| // ---------------------------------------------------------------------------- |
| |
| void PDataManager::RegisterPdata(RUNTIME_FUNCTION* pdataStart, _In_ const ULONG_PTR functionStart, _In_ const ULONG_PTR functionEnd, _Out_ PVOID* pdataTable, ULONG entryCount, ULONG maxEntryCount) |
| { |
| BOOLEAN success = FALSE; |
| HRESULT hr = S_OK; |
| if (AutoSystemInfo::Data.IsWin8OrLater()) |
| { |
| Assert(pdataTable != NULL); |
| |
| // Since we do not expect many thunk functions to be created, we are using 1 table/function |
| // for now. This can be optimized further if needed. |
| NTSTATUS status = NtdllLibrary::Instance->AddGrowableFunctionTable(pdataTable, |
| pdataStart, |
| entryCount, |
| maxEntryCount, |
| /*RangeBase*/ functionStart, |
| /*RangeEnd*/ functionEnd); |
| success = NT_SUCCESS(status); |
| Assert(!success || pdataTable); |
| hr = status; |
| } |
| else |
| { |
| *pdataTable = pdataStart; |
| success = RtlAddFunctionTable(pdataStart, entryCount, functionStart); |
| if (!success) |
| { |
| hr = E_OUTOFMEMORY; // only OOM error can happen for RtlAddFunctionTable |
| } |
| } |
| if (!success) |
| { |
| Js::Throw::XDataRegistrationError(hr, functionStart); |
| } |
| } |
| |
| void PDataManager::UnregisterPdata(RUNTIME_FUNCTION* pdata) |
| { |
| if (AutoSystemInfo::Data.IsWin8OrLater()) |
| { |
| NtdllLibrary::Instance->DeleteGrowableFunctionTable(pdata); |
| } |
| else |
| { |
| BOOLEAN success = RtlDeleteFunctionTable(pdata); |
| Assert(success); |
| } |
| } |
| |
| #else // !_WIN32 |
| |
| // ---------------------------------------------------------------------------- |
| // !_WIN32 x64 unwind uses .eh_frame |
| // ---------------------------------------------------------------------------- |
| |
| void PDataManager::RegisterPdata(RUNTIME_FUNCTION* pdataStart, |
| _In_ const ULONG_PTR functionStart, _In_ const ULONG_PTR functionEnd, |
| _Out_ PVOID* pdataTable, ULONG entryCount, ULONG maxEntryCount) |
| { |
| __REGISTER_FRAME(pdataStart); |
| *pdataTable = pdataStart; |
| } |
| |
| void PDataManager::UnregisterPdata(RUNTIME_FUNCTION* pdata) |
| { |
| __DEREGISTER_FRAME(pdata); |
| } |
| |
| #endif // !_WIN32 |
| #endif // PDATA_ENABLED |