From a5a4c2918e97068264d9f382ec2580ea30eb4e8b Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Tue, 5 Oct 2021 17:10:23 +0200 Subject: [PATCH 1/2] Reserve platform-reserved register on Windows AArch64 --- sdk/CHANGELOG.md | 1 + .../org.graalvm.nativeimage/snapshot.sigtest | 8 ++++++ .../services/org.graalvm.nativeimage.Platform | 1 + .../src/org/graalvm/nativeimage/Platform.java | 17 ++++++++++++ .../SubstrateAArch64RegisterConfig.java | 26 +++++++++++++------ 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index bc6ed53d69cf..25f7ec56b305 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -3,6 +3,7 @@ This changelog summarizes major changes between GraalVM SDK versions. The main focus is on APIs exported by GraalVM SDK. ## Version 22.0.0 +* (GR-31170) Native Image API: Added `WINDOWS_AARCH64` Platform. * (GR-33657) Native Image API: Added `CEntryPoint#include` attribute which can be used to controll if the entry point should be automatically added to the shared library. * (GR-22699)(EE-only) Added the ability to spawn a native-image isolate for a each `Engine` or `Context` by calling `Context.Builder.option("engine.SpawnIsolate", "true")`. This enables heap isolation between the host and guest applications. Using isolates improves security, startup and warmup time of polyglot languages. In this mode, calls between host and guest are more costly as they need to cross a native boundary. It is recommended to use the `HostAccess.SCOPED` policy with this mode to avoid strong cyclic references between host and guest. This mode is experimental in this release and only supported for a limited set of languages. diff --git a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest index 5dc7f0afe64f..aff5f2ca9518 100644 --- a/sdk/src/org.graalvm.nativeimage/snapshot.sigtest +++ b/sdk/src/org.graalvm.nativeimage/snapshot.sigtest @@ -226,6 +226,7 @@ innr public final static IOS_AARCH64 innr public final static IOS_AMD64 innr public final static LINUX_AARCH64 innr public final static WINDOWS_AMD64 +innr public final static WINDOWS_AARCH64 innr public static LINUX_AMD64 meth public java.lang.String getArchitecture() meth public java.lang.String getOS() @@ -327,6 +328,13 @@ intf org.graalvm.nativeimage.Platform$AMD64 intf org.graalvm.nativeimage.Platform$WINDOWS supr java.lang.Object +CLSS public final static org.graalvm.nativeimage.Platform$WINDOWS_AARCH64 + outer org.graalvm.nativeimage.Platform +cons public init() +intf org.graalvm.nativeimage.Platform$AARCH64 +intf org.graalvm.nativeimage.Platform$WINDOWS +supr java.lang.Object + CLSS public abstract interface !annotation org.graalvm.nativeimage.Platforms anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME) anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[TYPE, METHOD, CONSTRUCTOR, FIELD, PACKAGE]) diff --git a/sdk/src/org.graalvm.nativeimage/src/META-INF/services/org.graalvm.nativeimage.Platform b/sdk/src/org.graalvm.nativeimage/src/META-INF/services/org.graalvm.nativeimage.Platform index b3e6d2df87a9..035172aa9f70 100644 --- a/sdk/src/org.graalvm.nativeimage/src/META-INF/services/org.graalvm.nativeimage.Platform +++ b/sdk/src/org.graalvm.nativeimage/src/META-INF/services/org.graalvm.nativeimage.Platform @@ -6,3 +6,4 @@ org.graalvm.nativeimage.Platform$DARWIN_AARCH64 org.graalvm.nativeimage.Platform$IOS_AMD64 org.graalvm.nativeimage.Platform$IOS_AARCH64 org.graalvm.nativeimage.Platform$WINDOWS_AMD64 +org.graalvm.nativeimage.Platform$WINDOWS_AARCH64 diff --git a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java index 1369f0663019..1c6776533958 100644 --- a/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java +++ b/sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/Platform.java @@ -369,6 +369,23 @@ public WINDOWS_AMD64() { } + /** + * Supported leaf platform: Windows on AArch 64-bit. + * + * @since 22.0 + */ + final class WINDOWS_AARCH64 implements WINDOWS, AARCH64 { + + /** + * Instantiates a marker instance of this platform. + * + * @since 22.0 + */ + public WINDOWS_AARCH64() { + } + + } + /** * Marker for elements (types, methods, or fields) that are only visible during native image * generation and cannot be used at run time, regardless of the actual platform. diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java index b39ba697c41c..0acc02097d7d 100755 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64RegisterConfig.java @@ -101,7 +101,7 @@ public class SubstrateAArch64RegisterConfig implements SubstrateRegisterConfig { private final TargetDescription target; private final int nativeParamsStackOffset; private final RegisterArray generalParameterRegs; - private final RegisterArray simdParameterRegs; + private final RegisterArray fpParameterRegs; private final RegisterArray allocatableRegs; private final RegisterArray calleeSaveRegisters; private final RegisterAttributes[] attributesMap; @@ -114,9 +114,16 @@ public SubstrateAArch64RegisterConfig(ConfigKind config, MetaAccessProvider meta this.metaAccess = metaAccess; this.preserveFramePointer = preserveFramePointer; - // This is the Linux 64-bit ABI for parameters. + /* + * This is the Linux 64-bit ABI for parameters. + * + * Note the Darwin and Windows ABI are the same with the following exception: + * + * On Windows, when calling a method with variadic args, all fp parameters must be passed on + * the stack. Currently, this is unsupported. Adding support is tracked by GR-34188. + */ generalParameterRegs = new RegisterArray(r0, r1, r2, r3, r4, r5, r6, r7); - simdParameterRegs = new RegisterArray(v0, v1, v2, v3, v4, v5, v6, v7); + fpParameterRegs = new RegisterArray(v0, v1, v2, v3, v4, v5, v6, v7); nativeParamsStackOffset = 0; @@ -141,10 +148,13 @@ public SubstrateAArch64RegisterConfig(ConfigKind config, MetaAccessProvider meta regs.remove(ReservedRegisters.singleton().getHeapBaseRegister()); regs.remove(ReservedRegisters.singleton().getThreadRegister()); /* - * Darwin specifies that r18 is a platform-reserved register: + * Darwin and Windows specify that r18 is a platform-reserved register: + * * https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms + * + * https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions */ - if (OS.getCurrent() == OS.DARWIN) { + if (OS.getCurrent() == OS.DARWIN || OS.getCurrent() == OS.WINDOWS) { regs.remove(r18); } allocatableRegs = new RegisterArray(regs); @@ -229,7 +239,7 @@ public CallingConvention getCallingConvention(Type t, JavaType returnType, JavaT AllocatableValue[] locations = new AllocatableValue[parameterTypes.length]; int currentGeneral = 0; - int currentSIMD = 0; + int currentFP = 0; /* * We have to reserve a slot between return address and outgoing parameters for the deopt @@ -261,8 +271,8 @@ public CallingConvention getCallingConvention(Type t, JavaType returnType, JavaT break; case Float: case Double: - if (currentSIMD < simdParameterRegs.size()) { - register = simdParameterRegs.get(currentSIMD++); + if (currentFP < fpParameterRegs.size()) { + register = fpParameterRegs.get(currentFP++); } break; default: From 0c24d67d194819dad45c3682d1b8eba391cf0cfe Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Wed, 13 Oct 2021 21:00:28 +0200 Subject: [PATCH 2/2] Add Relocation information for Mach-O AArch64. --- .../src/com/oracle/objectfile/ObjectFile.java | 11 + .../macho/MachORelocationElement.java | 212 ++++++++++++------ .../macho/MachOUserDefinedSection.java | 78 +++++-- 3 files changed, 212 insertions(+), 89 deletions(-) diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java index 5484b9f97b49..4bf21afddb05 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java @@ -274,6 +274,9 @@ public enum RelocationKind { PC_RELATIVE_2, PC_RELATIVE_4, PC_RELATIVE_8, + /** + * AArch64-specific relocation types. + */ AARCH64_R_MOVW_UABS_G0, AARCH64_R_MOVW_UABS_G0_NC, AARCH64_R_MOVW_UABS_G1, @@ -345,6 +348,14 @@ public static int getRelocationSize(RelocationKind kind) { case PC_RELATIVE_4: case SECREL_4: return 4; + case AARCH64_R_AARCH64_ADR_PREL_PG_HI21: + case AARCH64_R_AARCH64_LDST64_ABS_LO12_NC: + case AARCH64_R_AARCH64_LDST32_ABS_LO12_NC: + case AARCH64_R_AARCH64_LDST16_ABS_LO12_NC: + case AARCH64_R_AARCH64_LDST8_ABS_LO12_NC: + case AARCH64_R_AARCH64_ADD_ABS_LO12_NC: + // AArch64 instructions are 4 bytes + return 4; case DIRECT_8: case PC_RELATIVE_8: return 8; diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java index 1c454c06e53e..8179d3a36ff0 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java @@ -30,6 +30,8 @@ import java.util.Set; import java.util.TreeMap; +import org.graalvm.compiler.core.common.NumUtil; + import com.oracle.objectfile.BuildDependency; import com.oracle.objectfile.LayoutDecisionMap; import com.oracle.objectfile.ObjectFile; @@ -47,14 +49,21 @@ class MachORelocationElement extends MachOObjectFile.LinkEditElement { /* * We are a bunch of RelocationInfo.Structs grouped by relocated section, ordered by the offset - * within the section. + * within the section. Note also that, when present, an explicit addend for a given offset must + * be stored immediately before its corresponding record. */ private static int compareSectionThenOffset(MachORelocationInfo p, MachORelocationInfo q) { if (!p.getRelocatedSection().equals(q.getRelocatedSection())) { return p.getRelocatedSection().hashCode() - q.getRelocatedSection().hashCode(); } - return Math.toIntExact(p.getOffset() - q.getOffset()); + if (p.getOffset() != q.getOffset()) { + return Math.toIntExact(p.getOffset() - q.getOffset()); + } + + assert !(p.isAddendKind() && q.isAddendKind()) : "two addends for same relocation"; + // reverse arguments since want the addend kind first + return Boolean.compare(q.isAddendKind(), p.isAddendKind()); } private Map infos = new TreeMap<>(MachORelocationElement::compareSectionThenOffset); @@ -116,56 +125,100 @@ public int countFor(MachOSection s) { } } +interface MachORelocationType { + boolean isPCRelative(); + + int getValue(); +} + /** - * These are defined as an enum in - * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/x86_64/reloc.h#L173 + * These are defined as an enum in EXTERNAL_HEADERS/mach-o/x86_64/reloc.h#L173 * which we reproduce. Of course, take care to preserve the order! * - * For examples of how these symbols are used, see the linked file above and - * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h. + * For examples of how these symbols are used, see the linked file above and EXTERNAL_HEADERS/mach-o/reloc.h. */ -enum X86_64Reloc { - UNSIGNED, // for absolute addresses - SIGNED, // for signed 32-bit displacement - BRANCH, // a CALL/JMP instruction with 32-bit displacement - GOT_LOAD, // a MOVQ load of a GOT entry - GOT, // other GOT references - SUBTRACTOR, // must be followed by a X86_64_RELOC_UNSIGNED - SIGNED_1, // for signed 32-bit displacement with a -1 addend - SIGNED_2, // for signed 32-bit displacement with a -2 addend - SIGNED_4, // for signed 32-bit displacement with a -4 addend - TLV; // for thread local variables +enum X86_64Reloc implements MachORelocationType { + UNSIGNED(0), // for absolute addresses + SIGNED(1, true), // for signed 32-bit displacement + BRANCH(2), // a CALL/JMP instruction with 32-bit displacement + GOT_LOAD(3), // a MOVQ load of a GOT entry + GOT(4), // other GOT references + SUBTRACTOR(5), // must be followed by a X86_64_RELOC_UNSIGNED + SIGNED_1(6, true), // for signed 32-bit displacement with a -1 addend + SIGNED_2(7, true), // for signed 32-bit displacement with a -2 addend + SIGNED_4(8, true), // for signed 32-bit displacement with a -4 addend + TLV(9); // for thread local variables + + private final boolean pcRelative; + private final int value; + X86_64Reloc(int value) { + this.value = value; + pcRelative = false; + } + + X86_64Reloc(int value, boolean pcRelative) { + this.value = value; + this.pcRelative = pcRelative; + } + + @Override + public boolean isPCRelative() { + return pcRelative; + } + + @Override public int getValue() { - return ordinal(); + return value; } } /** - * These are defined as an enum in - * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm64/reloc.h#L26, + * These are defined as an enum in EXTERNAL_HEADERS/mach-o/arm64/reloc.h#L26, * which we reproduce. Of course, take care to preserve the order! * - * For examples of how these symbols are used, see - * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/arm/reloc.h - * (for AArch32 information, but does provide some insight) and - * https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/EXTERNAL_HEADERS/mach-o/reloc.h. + * For examples of how these symbols are used, see EXTERNAL_HEADERS/mach-o/arm/reloc.h + * (for AArch32 information, but does provide some insight) and EXTERNAL_HEADERS/mach-o/reloc.h. */ -enum ARM64Reloc { - UNSIGNED, // for pointers - SUBTRACTOR, // must be followed by a ARM64_RELOC_UNSIGNED - BRANCH26, // a B/BL instruction with 26-bit displacement - PAGE21, // pc-rel distance to page of target - PAGEOFF12, // offset within page, scaled by r_length - GOT_LOAD_PAGE21, // pc-rel distance to page of GOT slot - GOT_LOAD_PAGEOFF12, // offset within page of GOT slot, scaled by r_length - POINTER_TO_GOT, // for pointers to GOT slots - TLVP_LOAD_PAGE21, // pc-rel distance to page of TLVP slot - TLVP_LOAD_PAGEOFF12, // offset within page of TLVP slot, scaled by r_length - ADDEND; // must be followed by PAGE21 or PAGEOFF12 +enum ARM64Reloc implements MachORelocationType { + UNSIGNED(0), // for pointers + SUBTRACTOR(1), // must be followed by a ARM64_RELOC_UNSIGNED + BRANCH26(2), // a B/BL instruction with 26-bit displacement + PAGE21(3, true), // pc-rel distance to page of target + PAGEOFF12(4), // offset within page, scaled by r_length + GOT_LOAD_PAGE21(5, true), // pc-rel distance to page of GOT slot + GOT_LOAD_PAGEOFF12(6), // offset within page of GOT slot, scaled by r_length + POINTER_TO_GOT(7), // for pointers to GOT slots + TLVP_LOAD_PAGE21(8, true), // pc-rel distance to page of TLVP slot + TLVP_LOAD_PAGEOFF12(9), // offset within page of TLVP slot, scaled by r_length + ADDEND(10); // must be followed by PAGE21 or PAGEOFF12 + + private final boolean pcRelative; + private final int value; + + ARM64Reloc(int value) { + this.value = value; + pcRelative = false; + } + + ARM64Reloc(int value, boolean pcRelative) { + this.value = value; + this.pcRelative = pcRelative; + } + @Override + public boolean isPCRelative() { + return pcRelative; + } + + @Override public int getValue() { - return ordinal(); + return value; } } @@ -173,11 +226,12 @@ final class MachORelocationInfo implements RelocationRecord, RelocationMethod { private final MachORelocationElement containingElement; private final MachOSection relocatedSection; - private final RelocationKind kind; + private final MachORelocationType kind; private final int sectionOffset; private final Symbol sym; private final MachOSection targetSection; private final byte log2length; + private final int addend; /** * Construct a relocation record. @@ -189,7 +243,8 @@ final class MachORelocationInfo implements RelocationRecord, RelocationMethod { * @param kind the kind of relocation to perform at the relocation site * @param symbolName the symbol against which to relocate */ - MachORelocationInfo(MachORelocationElement containingElement, MachOSection relocatedSection, int offset, int requestedLength, RelocationKind kind, String symbolName, boolean asLocalReloc) { + private MachORelocationInfo(MachORelocationElement containingElement, MachOSection relocatedSection, int offset, int requestedLength, MachORelocationType kind, String symbolName, + boolean asLocalReloc, int addend) { this.containingElement = containingElement; this.relocatedSection = relocatedSection; this.sectionOffset = offset; // gets turned into a vaddr on write-out @@ -215,6 +270,20 @@ final class MachORelocationInfo implements RelocationRecord, RelocationMethod { // if the symbol is defined in the same file, i.e. locally, we have a target section assert !asLocalReloc || this.sym.isDefined(); this.targetSection = asLocalReloc ? (MachOSection) this.sym.getDefinedSection() : null; + this.addend = addend; + } + + /* Creates an ARM64_RELOC_ADDEND relocation type. */ + static MachORelocationInfo createARM64RelocAddend(MachORelocationElement containingElement, MachOSection relocatedSection, int offset, String symbolName, long addend) { + int length = 4; // This relocation record holds the addend for a 4-byte AArch64 instruction + return new MachORelocationInfo(containingElement, relocatedSection, offset, length, ARM64Reloc.ADDEND, symbolName, false, Math.toIntExact(addend)); + } + + static MachORelocationInfo createRelocation(MachORelocationElement containingElement, MachOSection relocatedSection, int offset, RelocationKind kind, String symbolName) { + int length = ObjectFile.RelocationKind.getRelocationSize(kind); + MachORelocationType type = getMachORelocationType(relocatedSection, kind); + return new MachORelocationInfo(containingElement, relocatedSection, offset, length, type, symbolName, false, 0); + } public static int getEncodedSize() { @@ -225,7 +294,12 @@ public void write(OutputAssembler oa, @SuppressWarnings("unused") Map