Skip to content

Commit

Permalink
[GR-53007] Emit linker relocations for MethodPointers
Browse files Browse the repository at this point in the history
PullRequest: graal/17464
  • Loading branch information
lewurm committed Jun 20, 2024
2 parents 31132c5 + 06b7876 commit 850e3fe
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,14 @@

import java.util.function.Consumer;

import com.oracle.svm.core.meta.MethodPointer;
import com.oracle.svm.hosted.meta.HostedMethod;
import jdk.graal.compiler.asm.Assembler.CodeAnnotation;
import jdk.graal.compiler.asm.aarch64.AArch64Assembler.SingleInstructionAnnotation;
import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler;
import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler.MovSequenceAnnotation.MovAction;
import jdk.graal.compiler.code.CompilationResult;
import jdk.vm.ci.meta.VMConstant;
import org.graalvm.nativeimage.ImageSingletons;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;
Expand Down Expand Up @@ -169,17 +172,24 @@ class AdrpAddMacroInstructionHostedPatcher extends CompilationResult.CodeAnnotat

@Override
public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) {
Object relocVal = ref;
if (ref instanceof ConstantReference constantRef) {
VMError.guarantee(!(constantRef.getConstant() instanceof SubstrateMethodPointerConstant), "SubstrateMethodPointerConstants should not be relocated %s", constantRef);
VMConstant constant = constantRef.getConstant();
if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
MethodPointer pointer = methodPointerConstant.pointer();
HostedMethod hMethod = (HostedMethod) pointer.getMethod();
VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod);
relocVal = pointer;
}
} else {
VMError.guarantee(ref instanceof DataSectionReference || ref instanceof CGlobalDataReference, "Unexpected reference: %s", ref);
}

int siteOffset = compStart + macroInstruction.instructionPosition;
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, ref);
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADR_PREL_PG_HI21, relocVal);

siteOffset += 4;
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADD_ABS_LO12_NC, ref);
relocs.addRelocationWithoutAddend(siteOffset, RelocationKind.AARCH64_R_AARCH64_ADD_ABS_LO12_NC, relocVal);
}

@Uninterruptible(reason = ".")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,21 @@
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

import com.oracle.objectfile.ObjectFile;
import com.oracle.objectfile.ObjectFile.RelocationKind;
import com.oracle.svm.core.Uninterruptible;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.graal.code.CGlobalDataReference;
import com.oracle.svm.core.graal.code.PatchConsumerFactory;
import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton;
import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton;
import com.oracle.svm.core.meta.MethodPointer;
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.code.HostedImageHeapConstantPatch;
import com.oracle.svm.hosted.code.HostedPatcher;
import com.oracle.svm.hosted.image.RelocatableBuffer;
import com.oracle.svm.hosted.meta.HostedMethod;

import jdk.graal.compiler.asm.Assembler;
import jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.AddressDisplacementAnnotation;
Expand All @@ -52,6 +54,7 @@
import jdk.vm.ci.code.site.DataSectionReference;
import jdk.vm.ci.code.site.Reference;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.VMConstant;

@AutomaticallyRegisteredFeature
@Platforms({Platform.AMD64.class})
Expand Down Expand Up @@ -120,10 +123,23 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) {
* the relocation site, we want to subtract n bytes from our addend.
*/
long addend = (annotation.nextInstructionPosition - annotation.operandPosition);
relocs.addRelocationWithAddend((int) siteOffset, ObjectFile.RelocationKind.getPCRelative(annotation.operandSize), addend, ref);
} else if (ref instanceof ConstantReference constantRef) {
VMError.guarantee(!(constantRef.getConstant() instanceof SubstrateMethodPointerConstant), "SubstrateMethodPointerConstants should not be relocated %s", constantRef);
relocs.addRelocationWithoutAddend((int) siteOffset, ObjectFile.RelocationKind.getDirect(annotation.operandSize), ref);
assert addend == annotation.operandSize;
relocs.addRelocationWithAddend((int) siteOffset, RelocationKind.getPCRelative(annotation.operandSize), addend, ref);
} else if (ref instanceof ConstantReference constantReference) {
VMConstant constant = constantReference.getConstant();
if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
MethodPointer pointer = methodPointerConstant.pointer();
HostedMethod hMethod = (HostedMethod) pointer.getMethod();
VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod);

RelocationKind kindPCRelative = RelocationKind.getPCRelative(annotation.operandSize);
// lea instruction using rip relative addressing, account for additional offset
long addend = -RelocationKind.getRelocationSize(kindPCRelative);
relocs.addRelocationWithAddend((int) siteOffset, kindPCRelative, addend, pointer);
} else {
RelocationKind kindDirect = RelocationKind.getDirect(annotation.operandSize);
relocs.addRelocationWithoutAddend((int) siteOffset, kindDirect, constantReference);
}
} else {
throw VMError.shouldNotReachHere("Unknown type of reference in code");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
import com.oracle.objectfile.ObjectFile;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
import com.oracle.svm.core.util.VMError;
import com.oracle.svm.hosted.code.HostedDirectCallTrampolineSupport;
import com.oracle.svm.hosted.code.HostedImageHeapConstantPatch;
Expand All @@ -55,7 +54,6 @@
import jdk.graal.compiler.debug.Indent;
import jdk.vm.ci.code.TargetDescription;
import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.code.site.ConstantReference;
import jdk.vm.ci.code.site.DataPatch;
import jdk.vm.ci.code.site.Infopoint;
import jdk.vm.ci.code.site.Reference;
Expand Down Expand Up @@ -397,26 +395,18 @@ public void patchMethods(DebugContext debug, RelocatableBuffer relocs, ObjectFil
patchesHandled++;
}
}

for (DataPatch dataPatch : compilation.getDataPatches()) {
assert dataPatch.note == null : "Unexpected note: " + dataPatch.note;
Reference ref = dataPatch.reference;
var patcher = patches.get(dataPatch.pcOffset);
if (ref instanceof ConstantReference constant && constant.getConstant() instanceof SubstrateMethodPointerConstant methodPtrConstant) {
/*
* We directly patch SubstrateMethodPointerConstants.
*/
HostedMethod hMethod = (HostedMethod) methodPtrConstant.pointer().getMethod();
VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod);
int targetOffset = hMethod.getCodeAddressOffset();
int pcDisplacement = targetOffset - (compStart + dataPatch.pcOffset);
patcher.patch(compStart, pcDisplacement, compilation.getTargetCode());
} else {
/*
* Constants are allocated offsets in a separate space, which can be emitted as
* read-only (.rodata) section.
*/
patcher.relocate(ref, relocs, compStart);
}
/*
* Constants are (1) allocated offsets in a separate space, which can be emitted as
* read-only (.rodata) section, or (2) method pointers that are computed relative to
* the PC.
*/
patcher.relocate(ref, relocs, compStart);

boolean noPriorMatch = patchedOffsets.add(dataPatch.pcOffset);
VMError.guarantee(noPriorMatch, "Patching same offset twice.");
patchesHandled++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,9 @@ public static MethodPointerRelocationProvider singleton() {
}

public void markMethodPointerRelocation(ObjectFile.ProgbitsSectionImpl section, int offset, ObjectFile.RelocationKind relocationKind, HostedMethod target,
@SuppressWarnings("unused") boolean isStaticallyResolved) {
section.markRelocationSite(offset, relocationKind, localSymbolNameForMethod(target), 0L);
long addend, @SuppressWarnings("unused") boolean isStaticallyResolved) {
section.markRelocationSite(offset, relocationKind, localSymbolNameForMethod(target), addend);
}

}

@AutomaticallyRegisteredFeature
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,14 @@ private static void validateNoDirectRelocationsInTextSection(RelocatableBuffer.I
}
}

private static boolean checkMethodPointerRelocationKind(Info info) {
int wordSize = ConfigurationValues.getTarget().arch.getWordSize();
int relocationSize = info.getRelocationSize();
RelocationKind relocationKind = info.getRelocationKind();

return (relocationSize == wordSize && RelocationKind.isDirect(relocationKind)) || (relocationSize == 4 && RelocationKind.isPCRelative(relocationKind));
}

private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, final int offset, final RelocatableBuffer.Info info) {
assert info.getTargetObject() instanceof CFunctionPointer : "Wrong type for FunctionPointer relocation: " + info.getTargetObject().toString();

Expand All @@ -617,10 +625,10 @@ private void markFunctionRelocationSite(final ProgbitsSectionImpl sectionImpl, f
if (!target.isCompiled() && !target.wrapped.isInBaseLayer()) {
target = metaAccess.lookupJavaMethod(InvalidMethodPointerHandler.METHOD_POINTER_NOT_COMPILED_HANDLER_METHOD);
}

assert checkMethodPointerRelocationKind(info);
// A reference to a method. Mark the relocation site using the symbol name.
Architecture arch = ConfigurationValues.getTarget().arch;
assert (arch instanceof AArch64) || RelocationKind.getDirect(arch.getWordSize()) == info.getRelocationKind();
relocationProvider.markMethodPointerRelocation(sectionImpl, offset, info.getRelocationKind(), target, methodPointer.isAbsolute());
relocationProvider.markMethodPointerRelocation(sectionImpl, offset, info.getRelocationKind(), target, info.getAddend(), methodPointer.isAbsolute());
}

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

0 comments on commit 850e3fe

Please sign in to comment.