mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:39:49 +00:00
3a668dcf03
Fixes https://github.com/dart-lang/sdk/issues/52045 TEST=ffi_induce_a_crash_test Change-Id: Ic047df10732d6ff8cf695ce098d80ec3a098dbf9 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/302380 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Aprelev <aam@google.com>
80 lines
3.3 KiB
C++
80 lines
3.3 KiB
C++
// 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.
|
|
|
|
#include "vm/unwinding_records.h"
|
|
|
|
#include "vm/globals.h"
|
|
|
|
#include "platform/unwinding_records.h"
|
|
|
|
#if defined(DART_HOST_OS_WINDOWS) && defined(TARGET_ARCH_X64)
|
|
|
|
namespace dart {
|
|
|
|
static void InitUnwindingRecord(intptr_t offset,
|
|
CodeRangeUnwindingRecord* record,
|
|
size_t code_size_in_bytes) {
|
|
// All addresses are 32bit relative offsets to start.
|
|
record->runtime_function[0].BeginAddress = 0;
|
|
record->runtime_function[0].EndAddress = code_size_in_bytes;
|
|
record->runtime_function[0].UnwindData =
|
|
offset + offsetof(CodeRangeUnwindingRecord, unwind_info);
|
|
record->runtime_function_count = 1;
|
|
}
|
|
|
|
const void* UnwindingRecords::GenerateRecordsInto(intptr_t offset,
|
|
uint8_t* target_buffer) {
|
|
CodeRangeUnwindingRecord* record =
|
|
new (target_buffer) CodeRangeUnwindingRecord();
|
|
InitUnwindingRecord(offset, record, offset);
|
|
return target_buffer;
|
|
}
|
|
|
|
// Special exception-unwinding records are put at the end of executable
|
|
// page on Windows for 64-bit applications.
|
|
void UnwindingRecords::RegisterExecutablePage(Page* page) {
|
|
// Won't set up unwinding records on Windows 7, so users won't be able
|
|
// to benefit from proper unhandled exceptions filtering.
|
|
auto function = static_cast<decltype(&::RtlAddGrowableFunctionTable)>(
|
|
UnwindingRecordsPlatform::GetAddGrowableFunctionTableFunc());
|
|
if (function == nullptr) return;
|
|
ASSERT(page->is_executable());
|
|
ASSERT(sizeof(CodeRangeUnwindingRecord) <=
|
|
UnwindingRecordsPlatform::SizeInBytes());
|
|
page->top_ -= UnwindingRecordsPlatform::SizeInBytes();
|
|
intptr_t unwinding_record_offset =
|
|
page->memory_->size() - UnwindingRecordsPlatform::SizeInBytes();
|
|
CodeRangeUnwindingRecord* record =
|
|
new (reinterpret_cast<uint8_t*>(page->memory_->start()) +
|
|
unwinding_record_offset) CodeRangeUnwindingRecord();
|
|
InitUnwindingRecord(unwinding_record_offset, record, page->memory_->size());
|
|
if (function(
|
|
/*DynamicTable=*/&record->dynamic_table,
|
|
/*FunctionTable=*/record->runtime_function,
|
|
/*EntryCount=*/record->runtime_function_count,
|
|
/*MaximumEntryCount=*/record->runtime_function_count,
|
|
/*RangeBase=*/page->memory_->start(),
|
|
/*RangeEnd=*/page->memory_->end()) != 0) {
|
|
FATAL("Failed to add growable function table: %d\n", GetLastError());
|
|
}
|
|
}
|
|
|
|
void UnwindingRecords::UnregisterExecutablePage(Page* page) {
|
|
auto function = static_cast<decltype(&::RtlDeleteGrowableFunctionTable)>(
|
|
UnwindingRecordsPlatform::GetDeleteGrowableFunctionTableFunc());
|
|
if (function == nullptr) return;
|
|
ASSERT(page->is_executable() && !page->is_image());
|
|
intptr_t unwinding_record_offset =
|
|
page->memory_->size() - UnwindingRecordsPlatform::SizeInBytes();
|
|
CodeRangeUnwindingRecord* record =
|
|
reinterpret_cast<CodeRangeUnwindingRecord*>(
|
|
reinterpret_cast<uint8_t*>(page->memory_->start()) +
|
|
unwinding_record_offset);
|
|
function(record->dynamic_table);
|
|
}
|
|
|
|
} // namespace dart
|
|
|
|
#endif // defined(DART_HOST_OS_WINDOWS)
|