Skip to content

Commit 850e3fe

Browse files
committed
[GR-53007] Emit linker relocations for MethodPointers
PullRequest: graal/17464
2 parents 31132c5 + 06b7876 commit 850e3fe

File tree

5 files changed

+55
-32
lines changed

5 files changed

+55
-32
lines changed

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcherFeature.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@
2626

2727
import java.util.function.Consumer;
2828

29+
import com.oracle.svm.core.meta.MethodPointer;
30+
import com.oracle.svm.hosted.meta.HostedMethod;
2931
import jdk.graal.compiler.asm.Assembler.CodeAnnotation;
3032
import jdk.graal.compiler.asm.aarch64.AArch64Assembler.SingleInstructionAnnotation;
3133
import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler;
3234
import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler.MovSequenceAnnotation.MovAction;
3335
import jdk.graal.compiler.code.CompilationResult;
36+
import jdk.vm.ci.meta.VMConstant;
3437
import org.graalvm.nativeimage.ImageSingletons;
3538
import org.graalvm.nativeimage.Platform;
3639
import org.graalvm.nativeimage.Platforms;
@@ -169,17 +172,24 @@ class AdrpAddMacroInstructionHostedPatcher extends CompilationResult.CodeAnnotat
169172

170173
@Override
171174
public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) {
175+
Object relocVal = ref;
172176
if (ref instanceof ConstantReference constantRef) {
173-
VMError.guarantee(!(constantRef.getConstant() instanceof SubstrateMethodPointerConstant), "SubstrateMethodPointerConstants should not be relocated %s", constantRef);
177+
VMConstant constant = constantRef.getConstant();
178+
if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
179+
MethodPointer pointer = methodPointerConstant.pointer();
180+
HostedMethod hMethod = (HostedMethod) pointer.getMethod();
181+
VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod);
182+
relocVal = pointer;
183+
}
174184
} else {
175185
VMError.guarantee(ref instanceof DataSectionReference || ref instanceof CGlobalDataReference, "Unexpected reference: %s", ref);
176186
}
177187

178188
int siteOffset = compStart + macroInstruction.instructionPosition;
179-
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, ref);
189+
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, relocVal);
180190

181191
siteOffset += 4;
182-
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADD_ABS_LO12_NC, ref);
192+
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADD_ABS_LO12_NC, relocVal);
183193
}
184194

185195
@Uninterruptible(reason = ".")

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,21 @@
3030
import org.graalvm.nativeimage.Platform;
3131
import org.graalvm.nativeimage.Platforms;
3232

33-
import com.oracle.objectfile.ObjectFile;
33+
import com.oracle.objectfile.ObjectFile.RelocationKind;
3434
import com.oracle.svm.core.Uninterruptible;
3535
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3636
import com.oracle.svm.core.feature.InternalFeature;
3737
import com.oracle.svm.core.graal.code.CGlobalDataReference;
3838
import com.oracle.svm.core.graal.code.PatchConsumerFactory;
3939
import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton;
4040
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
41+
import com.oracle.svm.core.meta.MethodPointer;
4142
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
4243
import com.oracle.svm.core.util.VMError;
4344
import com.oracle.svm.hosted.code.HostedImageHeapConstantPatch;
4445
import com.oracle.svm.hosted.code.HostedPatcher;
4546
import com.oracle.svm.hosted.image.RelocatableBuffer;
47+
import com.oracle.svm.hosted.meta.HostedMethod;
4648

4749
import jdk.graal.compiler.asm.Assembler;
4850
import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.AddressDisplacementAnnotation;
@@ -52,6 +54,7 @@
5254
import jdk.vm.ci.code.site.DataSectionReference;
5355
import jdk.vm.ci.code.site.Reference;
5456
import jdk.vm.ci.meta.JavaConstant;
57+
import jdk.vm.ci.meta.VMConstant;
5558

5659
@AutomaticallyRegisteredFeature
5760
@Platforms({Platform.AMD64.class})
@@ -120,10 +123,23 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) {
120123
* the relocation site, we want to subtract n bytes from our addend.
121124
*/
122125
long addend = (annotation.nextInstructionPosition - annotation.operandPosition);
123-
relocs.addRelocationWithAddend((int) siteOffset, ObjectFile.RelocationKind.getPCRelative(annotation.operandSize), addend, ref);
124-
} else if (ref instanceof ConstantReference constantRef) {
125-
VMError.guarantee(!(constantRef.getConstant() instanceof SubstrateMethodPointerConstant), "SubstrateMethodPointerConstants should not be relocated %s", constantRef);
126-
relocs.addRelocationWithoutAddend((int) siteOffset, ObjectFile.RelocationKind.getDirect(annotation.operandSize), ref);
126+
assert addend == annotation.operandSize;
127+
relocs.addRelocationWithAddend((int) siteOffset, RelocationKind.getPCRelative(annotation.operandSize), addend, ref);
128+
} else if (ref instanceof ConstantReference constantReference) {
129+
VMConstant constant = constantReference.getConstant();
130+
if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
131+
MethodPointer pointer = methodPointerConstant.pointer();
132+
HostedMethod hMethod = (HostedMethod) pointer.getMethod();
133+
VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod);
134+
135+
RelocationKind kindPCRelative = RelocationKind.getPCRelative(annotation.operandSize);
136+
// lea instruction using rip relative addressing, account for additional offset
137+
long addend = -RelocationKind.getRelocationSize(kindPCRelative);
138+
relocs.addRelocationWithAddend((int) siteOffset, kindPCRelative, addend, pointer);
139+
} else {
140+
RelocationKind kindDirect = RelocationKind.getDirect(annotation.operandSize);
141+
relocs.addRelocationWithoutAddend((int) siteOffset, kindDirect, constantReference);
142+
}
127143
} else {
128144
throw VMError.shouldNotReachHere("Unknown type of reference in code");
129145
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import com.oracle.objectfile.ObjectFile;
4141
import com.oracle.svm.core.SubstrateOptions;
4242
import com.oracle.svm.core.config.ConfigurationValues;
43-
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
4443
import com.oracle.svm.core.util.VMError;
4544
import com.oracle.svm.hosted.code.HostedDirectCallTrampolineSupport;
4645
import com.oracle.svm.hosted.code.HostedImageHeapConstantPatch;
@@ -55,7 +54,6 @@
5554
import jdk.graal.compiler.debug.Indent;
5655
import jdk.vm.ci.code.TargetDescription;
5756
import jdk.vm.ci.code.site.Call;
58-
import jdk.vm.ci.code.site.ConstantReference;
5957
import jdk.vm.ci.code.site.DataPatch;
6058
import jdk.vm.ci.code.site.Infopoint;
6159
import jdk.vm.ci.code.site.Reference;
@@ -397,26 +395,18 @@ public void patchMethods(DebugContext debug, RelocatableBuffer relocs, ObjectFil
397395
patchesHandled++;
398396
}
399397
}
398+
400399
for (DataPatch dataPatch : compilation.getDataPatches()) {
401400
assert dataPatch.note == null : "Unexpected note: " + dataPatch.note;
402401
Reference ref = dataPatch.reference;
403402
var patcher = patches.get(dataPatch.pcOffset);
404-
if (ref instanceof ConstantReference constant && constant.getConstant() instanceof SubstrateMethodPointerConstant methodPtrConstant) {
405-
/*
406-
* We directly patch SubstrateMethodPointerConstants.
407-
*/
408-
HostedMethod hMethod = (HostedMethod) methodPtrConstant.pointer().getMethod();
409-
VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod);
410-
int targetOffset = hMethod.getCodeAddressOffset();
411-
int pcDisplacement = targetOffset - (compStart + dataPatch.pcOffset);
412-
patcher.patch(compStart, pcDisplacement, compilation.getTargetCode());
413-
} else {
414-
/*
415-
* Constants are allocated offsets in a separate space, which can be emitted as
416-
* read-only (.rodata) section.
417-
*/
418-
patcher.relocate(ref, relocs, compStart);
419-
}
403+
/*
404+
* Constants are (1) allocated offsets in a separate space, which can be emitted as
405+
* read-only (.rodata) section, or (2) method pointers that are computed relative to
406+
* the PC.
407+
*/
408+
patcher.relocate(ref, relocs, compStart);
409+
420410
boolean noPriorMatch = patchedOffsets.add(dataPatch.pcOffset);
421411
VMError.guarantee(noPriorMatch, "Patching same offset twice.");
422412
patchesHandled++;

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/MethodPointerRelocationProvider.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,9 @@ public static MethodPointerRelocationProvider singleton() {
3939
}
4040

4141
public void markMethodPointerRelocation(ObjectFile.ProgbitsSectionImpl section, int offset, ObjectFile.RelocationKind relocationKind, HostedMethod target,
42-
@SuppressWarnings("unused") boolean isStaticallyResolved) {
43-
section.markRelocationSite(offset, relocationKind, localSymbolNameForMethod(target), 0L);
42+
long addend, @SuppressWarnings("unused") boolean isStaticallyResolved) {
43+
section.markRelocationSite(offset, relocationKind, localSymbolNameForMethod(target), addend);
4444
}
45-
4645
}
4746

4847
@AutomaticallyRegisteredFeature

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,14 @@ private static void validateNoDirectRelocationsInTextSection(RelocatableBuffer.I
603603
}
604604
}
605605

606+
private static boolean checkMethodPointerRelocationKind(Info info) {
607+
int wordSize = ConfigurationValues.getTarget().arch.getWordSize();
608+
int relocationSize = info.getRelocationSize();
609+
RelocationKind relocationKind = info.getRelocationKind();
610+
611+
return (relocationSize == wordSize && RelocationKind.isDirect(relocationKind)) || (relocationSize == 4 && RelocationKind.isPCRelative(relocationKind));
612+
}
613+
606614
private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, final int offset, final RelocatableBuffer.Info info) {
607615
assert info.getTargetObject() instanceof CFunctionPointer : "Wrong type for FunctionPointer relocation: " + info.getTargetObject().toString();
608616

@@ -617,10 +625,10 @@ private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, f
617625
if (!target.isCompiled() && !target.wrapped.isInBaseLayer()) {
618626
target = metaAccess.lookupJavaMethod(InvalidMethodPointerHandler.METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD);
619627
}
628+
629+
assert checkMethodPointerRelocationKind(info);
620630
// A reference to a method. Mark the relocation site using the symbol name.
621-
Architecture arch = ConfigurationValues.getTarget().arch;
622-
assert (arch instanceof AArch64) || RelocationKind.getDirect(arch.getWordSize()) == info.getRelocationKind();
623-
relocationProvider.markMethodPointerRelocation(sectionImpl, offset, info.getRelocationKind(), target, methodPointer.isAbsolute());
631+
relocationProvider.markMethodPointerRelocation(sectionImpl, offset, info.getRelocationKind(), target, info.getAddend(), methodPointer.isAbsolute());
624632
}
625633

626634
private static boolean isAddendAligned(Architecture arch, long addend, RelocationKind kind) {

0 commit comments

Comments
 (0)