1 /*
  2  *  Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
  3  *  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  *  This code is free software; you can redistribute it and/or modify it
  6  *  under the terms of the GNU General Public License version 2 only, as
  7  *  published by the Free Software Foundation.  Oracle designates this
  8  *  particular file as subject to the "Classpath" exception as provided
  9  *  by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  *  This code is distributed in the hope that it will be useful, but WITHOUT
 12  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  *  version 2 for more details (a copy is included in the LICENSE file that
 15  *  accompanied this code).
 16  *
 17  *  You should have received a copy of the GNU General Public License version
 18  *  2 along with this work; if not, write to the Free Software Foundation,
 19  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  *   Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  *  or visit www.oracle.com if you need additional information or have any
 23  *  questions.
 24  *
 25  */
 26 package jdk.incubator.foreign;
 27 
 28 import jdk.internal.foreign.SystemLookup;
 29 import jdk.internal.foreign.abi.SharedUtils;
 30 import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker;
 31 import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker;
 32 import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker;
 33 import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker;
 34 import jdk.internal.reflect.CallerSensitive;
 35 import jdk.internal.reflect.Reflection;
 36 
 37 import java.lang.invoke.MethodHandle;
 38 import java.util.Optional;
 39 
 40 /**
 41  * A C linker implements the C Application Binary Interface (ABI) calling conventions.
 42  * Instances of this interface can be used to link foreign functions in native libraries that
 43  * follow the JVM's target platform C ABI. A C linker provides two main capabilities: first, it allows Java code
 44  * to <em>link</em> foreign functions into a so called <em>downcall method handle</em>; secondly, it allows
 45  * native code to call Java method handles via the generation of <em>upcall stubs</em>.
 46  * <p>
 47  * On unsupported platforms this class will fail to initialize with an {@link ExceptionInInitializerError}.
 48  * <p>
 49  * Unless otherwise specified, passing a {@code null} argument, or an array argument containing one or more {@code null}
 50  * elements to a method in this class causes a {@link NullPointerException NullPointerException} to be thrown. </p>
 51  *
 52  * <h2><a id = "downcall-method-handles">Downcall method handles</a></h2>
 53  * <p>
 54  * {@linkplain #downcallHandle(FunctionDescriptor) Linking a foreign function} is a process which requires a function descriptor,
 55  * a set of memory layouts which, together, specify the signature of the foreign function to be linked, and returns,
 56  * when complete, a downcall method handle, that is, a method handle that can be used to invoke the target native function.
 57  * The Java {@link java.lang.invoke.MethodType method type} associated with the returned method handle is derived from the
 58  * argument and return layouts in the function descriptor. More specifically, given each layout {@code L} in the
 59  * function descriptor, a corresponding carrier {@code C} is inferred, as described below:
 60  * <ul>
 61  * <li>if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases:
 62  *     <ul>
 63  *         <li>if {@code L} occurs in a parameter position and {@code E} is {@code MemoryAddress.class},
 64  *         then {@code C = Addressable.class};</li>
 65  *         <li>otherwise, {@code C = E};
 66  *     </ul></li>
 67  * <li>or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
 68  * </ul>
 69  * <p>
 70  * Arguments of type {@link MemorySegment}, {@link VaList} and {@link NativeSymbol} passed by-reference to a downcall method handle
 71  * are {@linkplain ResourceScope#keepAlive(ResourceScope) kept alive} by the linker implementation. That is, the resource
 72  * scope associated with such arguments cannot be closed, either implicitly or {@linkplain ResourceScope#close() explicitly}
 73  * until the downcall method handle completes.
 74  * <p>
 75  * Furthermore, if the function descriptor's return layout is a group layout, the resulting downcall method handle accepts
 76  * an extra parameter of type {@link SegmentAllocator}, which is used by the linker runtime to allocate the
 77  * memory region associated with the struct returned by  the downcall method handle.
 78  * <p>
 79  * Finally, downcall method handles feature a leading parameter of type {@link NativeSymbol}, from which the
 80  * address of the target native function can be derived. The address, when known statically, can also be provided by
 81  * clients at link time. As for other by-reference parameters (see above) this leading parameter will be
 82  * {@linkplain ResourceScope#keepAlive(ResourceScope) kept alive} by the linker implementation.
 83  * <p>Variadic functions, declared in C either with a trailing ellipses ({@code ...}) at the end of the formal parameter
 84  * list or with an empty formal parameter list, are not supported directly. However, it is possible to link a native
 85  * variadic function by using a {@linkplain FunctionDescriptor#asVariadic(MemoryLayout...) <em>variadic</em>} function descriptor,
 86  * in which the specialized signature of a given variable arity callsite is described in full. Alternatively,
 87  * if the foreign library allows it, clients might also be able to interact with variable arity methods
 88  * using by passing a trailing parameter of type {@link VaList}.
 89  *
 90  * <h2><a id = "upcall-stubs">Upcall stubs</a></h2>
 91  *
 92  * {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, ResourceScope) Creating an upcall stub} requires a method
 93  * handle and a function descriptor; in this case, the set of memory layouts in the function descriptor
 94  * specify the signature of the function pointer associated with the upcall stub.
 95  * <p>
 96  * The type of the provided method handle has to match the Java {@link java.lang.invoke.MethodType method type}
 97  * associated with the upcall stub, which is derived from the argument and return layouts in the function descriptor.
 98  * More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, as described below:
 99  * <ul>
100  * <li>if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases:
101  *     <ul>
102  *         <li>if {@code L} occurs in a return position and {@code E} is {@code MemoryAddress.class},
103  *         then {@code C = Addressable.class};</li>
104  *         <li>otherwise, {@code C = E};
105  *     </ul></li>
106  * <li>or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}</li>
107  * </ul>
108  * Upcall stubs are modelled by instances of type {@link NativeSymbol}; upcall stubs can be passed by reference to other
109  * downcall method handles (as {@link NativeSymbol} implements the {@link Addressable} interface) and,
110  * when no longer required, they can be {@link ResourceScope#close() released}, via their {@linkplain NativeSymbol#scope() scope}.
111  *
112  * <h2>System lookup</h2>
113  *
114  * This class implements the {@link SymbolLookup} interface; as such clients can {@linkplain #lookup(String) lookup} symbols
115  * in the standard libraries associated with this linker. The set of symbols available for lookup is unspecified,
116  * as it depends on the platform and on the operating system.
117  *
118  * @implSpec
119  * Implementations of this interface are immutable, thread-safe and <a href="{@docRoot}/java.base/java/lang/doc-files/ValueBased.html">value-based</a>.
120  */
121 public sealed interface CLinker extends SymbolLookup permits Windowsx64Linker, SysVx64Linker, LinuxAArch64Linker, MacOsAArch64Linker {
122 
123     /**
124      * Returns the C linker for the current platform.
125      * <p>
126      * This method is <a href="package-summary.html#restricted"><em>restricted</em></a>.
127      * Restricted methods are unsafe, and, if used incorrectly, their use might crash
128      * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on
129      * restricted methods, and use safe and supported functionalities, where possible.
130      *
131      * @return a linker for this system.
132      * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option
133      * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or
134      * {@code ALL-UNNAMED} in case {@code M} is an unnamed module.
135      */
136     @CallerSensitive
137     static CLinker systemCLinker() {
138         Reflection.ensureNativeAccess(Reflection.getCallerClass());
139         return SharedUtils.getSystemLinker();
140     }
141 
142     /**
143      * Lookup a symbol in the standard libraries associated with this linker.
144      * The set of symbols available for lookup is unspecified, as it depends on the platform and on the operating system.
145      * @return a linker-specific library lookup which is suitable to find symbols in the standard libraries associated with this linker.
146      */
147     @Override
148     default Optional<NativeSymbol> lookup(String name) {
149         return SystemLookup.getInstance().lookup(name);
150     }
151 
152     /**
153      * Obtains a foreign method handle, with the given type and featuring the given function descriptor,
154      * which can be used to call a target foreign function at the address in the given native symbol.
155      * <p>
156      * If the provided method type's return type is {@code MemorySegment}, then the resulting method handle features
157      * an additional prefix parameter, of type {@link SegmentAllocator}, which will be used by the linker runtime
158      * to allocate structs returned by-value.
159      * <p>
160      * Calling this method is equivalent to the following code:
161 <blockquote><pre>{@code
162     linker.downcallHandle(function).bindTo(symbol);
163 }</pre></blockquote>
164      *
165      * @param symbol   downcall symbol.
166      * @param function the function descriptor.
167      * @return the downcall method handle. The method handle type is <a href="CLinker.html#downcall-method-handles"><em>inferred</em></a>
168      * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout,
169      * or if the symbol is {@link MemoryAddress#NULL}
170      *
171      * @see SymbolLookup
172      */
173     default MethodHandle downcallHandle(NativeSymbol symbol, FunctionDescriptor function) {
174         SharedUtils.checkSymbol(symbol);
175         return downcallHandle(function).bindTo(symbol);
176     }
177 
178     /**
179      * Obtains a foreign method handle, with the given type and featuring the given function descriptor, which can be
180      * used to call a target foreign function at the address in a dynamically provided native symbol.
181      * The resulting method handle features a prefix parameter (as the first parameter) corresponding to the foreign function
182      * entry point, of type {@link NativeSymbol}.
183      * <p>
184      * If the provided function descriptor's return layout is a {@link GroupLayout}, then the resulting method handle features an
185      * additional prefix parameter (inserted immediately after the address parameter), of type {@link SegmentAllocator}),
186      * which will be used by the linker runtime to allocate structs returned by-value.
187      * <p>
188      * The returned method handle will throw an {@link IllegalArgumentException} if the native symbol passed to it is
189      * associated with the {@link MemoryAddress#NULL} address, or a {@link NullPointerException} if the native symbol is {@code null}.
190      *
191      * @param function the function descriptor.
192      * @return the downcall method handle. The method handle type is <a href="CLinker.html#downcall-method-handles"><em>inferred</em></a>
193      * from the provided function descriptor.
194      * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout.
195      *
196      * @see SymbolLookup
197      */
198     MethodHandle downcallHandle(FunctionDescriptor function);
199 
200     /**
201      * Allocates a native stub with given scope which can be passed to other foreign functions (as a function pointer);
202      * calling such a function pointer from native code will result in the execution of the provided method handle.
203      *
204      * <p>
205      * The returned function pointer is associated with the provided scope. When such scope is closed,
206      * the corresponding native stub will be deallocated.
207      * <p>
208      * The target method handle should not throw any exceptions. If the target method handle does throw an exception,
209      * the VM will exit with a non-zero exit code. To avoid the VM aborting due to an uncaught exception, clients
210      * could wrap all code in the target method handle in a try/catch block that catches any {@link Throwable}, for
211      * instance by using the {@link java.lang.invoke.MethodHandles#catchException(MethodHandle, Class, MethodHandle)}
212      * method handle combinator, and handle exceptions as desired in the corresponding catch block.
213      *
214      * @param target   the target method handle.
215      * @param function the function descriptor.
216      * @param scope the upcall stub scope.
217      * @return the native stub symbol.
218      * @throws IllegalArgumentException if the provided descriptor contains either a sequence or a padding layout,
219      * or if it is determined that the target method handle can throw an exception, or if the target method handle
220      * has a type that does not match the upcall stub <a href="CLinker.html#upcall-stubs"><em>inferred type</em></a>.
221      * @throws IllegalStateException if {@code scope} has been already closed, or if access occurs from a thread other
222      * than the thread owning {@code scope}.
223      */
224     NativeSymbol upcallStub(MethodHandle target, FunctionDescriptor function, ResourceScope scope);
225 }