================ @@ -0,0 +1,424 @@ +//===-- lib/runtime/trampoline.cpp -------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// W^X-compliant trampoline pool implementation. +// +// This file implements a runtime trampoline pool that maintains separate +// memory regions for executable code (RX) and writable data (RW). +// +// On Linux the code region transitions RW → RX (never simultaneously W+X). +// On macOS Apple Silicon the code region uses MAP_JIT with per-thread W^X +// toggling via pthread_jit_write_protect_np, so the mapping permissions +// include both W and X but hardware enforces that only one is active at +// a time on any given thread. +// +// Architecture: +// - Code region (RX): Contains pre-assembled trampoline stubs that load +// callee address and static chain from a paired TDATA entry, then jump +// to the callee with the static chain in the appropriate register. +// - Data region (RW): Contains TrampolineData entries with {callee_address, +// static_chain_address} pairs, one per trampoline slot. +// - Free list: Tracks available trampoline slots for O(1) alloc/free. +// +// Thread safety: Uses Fortran::runtime::Lock (pthreads on POSIX, +// CRITICAL_SECTION on Windows) — not std::mutex — to avoid C++ runtime +// library dependence. A single global lock serializes pool operations. +// This is a deliberate V1 design choice to keep the initial W^X +// architectural change minimal. Per-thread lock-free pools are deferred +// to a future optimization patch. +// +// AddressSanitizer note: The trampoline code region is allocated via +// mmap (not malloc/new), so ASan does not track it. The data region +// and handles are allocated via malloc (through AllocateMemoryOrCrash), +// which ASan intercepts normally. No special annotations are needed. +// +// See flang/docs/InternalProcedureTrampolines.md for design details. +// +//===----------------------------------------------------------------------===// + +#include "flang/Runtime/trampoline.h" +#include "flang-rt/runtime/lock.h" +#include "flang-rt/runtime/memory.h" +#include "flang-rt/runtime/terminator.h" +#include "flang-rt/runtime/trampoline.h" + +#include <cassert> +#include <cstdint> +#include <cstdlib> +#include <cstring> +#include <new> // For placement-new only (no operator new/delete dependency) + +// Platform-specific headers for memory mapping. +#if defined(_WIN32) +#include <windows.h> +#else +#include <sys/mman.h> +#include <unistd.h> +#endif + +// macOS Apple Silicon requires MAP_JIT and pthread_jit_write_protect_np +// to create executable memory under the hardened runtime. +#if defined(__APPLE__) && defined(__aarch64__) +#include <libkern/OSCacheControl.h> +#include <pthread.h> +#endif + +// Architecture support check. Stub generators exist only for x86-64 and +// AArch64. On other architectures the file compiles but the runtime API +// functions crash with a diagnostic if actually called, so that building +// flang-rt on e.g. RISC-V or PPC64 never fails. +#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) || \ ---------------- Saieiei wrote:
`Flang.cpp::addCodegenOptions` now checks the target triple before forwarding `-fruntime-trampoline`. On unsupported architectures (anything other than x86-64 / AArch64), the driver emits `warn_drv_unsupported_option_for_target` and silently drops the flag. The runtime `crashIfUnsupported()` guard remains as a safety net. https://github.com/llvm/llvm-project/pull/183108 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
