Skip to content

Commit e30698b

Browse files
committed
[GR-43389] [darwin-amd64] Workaround for buggy ld64 versions
Some versions of `ld64` cannot deal with DIRECT8 relocations in the `.text` section. Approximately this is since version 820.1 (Xcode 14). Starting with Xcode15 beta3 the default linker has been replaced with "the new linker" (version 902.11) which does not suffer from this bug anymore. However, Xcode also ships a `ld-classic` which reassembles "the old linker" and is still affected by this bug (and it of course prints the same version number). See some more in-depth analysis of this ld64 bug in https://openradar.appspot.com/FB11942354 The workaround: Instead of emitting the address of a HostedMethod inlined, it will be put in the data section and thus requires a memory load to obtain it.
1 parent f66c6bc commit e30698b

File tree

6 files changed

+68
-25
lines changed

6 files changed

+68
-25
lines changed

substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64LoadMethodPointerConstantOp.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
2929
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
3030

31+
import com.oracle.svm.core.FrameAccess;
32+
import org.graalvm.compiler.asm.amd64.AMD64Address;
3133
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
3234
import org.graalvm.compiler.lir.LIRInstructionClass;
3335
import org.graalvm.compiler.lir.StandardOp;
@@ -38,6 +40,7 @@
3840

3941
import jdk.vm.ci.code.Register;
4042
import jdk.vm.ci.meta.AllocatableValue;
43+
import org.graalvm.nativeimage.Platform;
4144

4245
public final class AMD64LoadMethodPointerConstantOp extends AMD64LIRInstruction implements StandardOp.LoadConstantOp {
4346
public static final LIRInstructionClass<AMD64LoadMethodPointerConstantOp> TYPE = LIRInstructionClass.create(AMD64LoadMethodPointerConstantOp.class);
@@ -53,8 +56,13 @@ public final class AMD64LoadMethodPointerConstantOp extends AMD64LIRInstruction
5356
@Override
5457
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
5558
Register resultReg = asRegister(result);
56-
crb.recordInlineDataInCode(constant);
57-
masm.movq(resultReg, 0L, true);
59+
if (!Platform.includedIn(Platform.DARWIN_AMD64.class)) {
60+
crb.recordInlineDataInCode(constant);
61+
masm.movq(resultReg, 0L, true);
62+
} else {
63+
/* [GR-43389] ld64 bug does not allow direct8 relocations in .text on darwin */
64+
masm.movq(resultReg, (AMD64Address) crb.recordDataReferenceInCode(constant, FrameAccess.wordSize()));
65+
}
5866
}
5967

6068
@Override

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDataBuilder.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
import java.nio.ByteBuffer;
3030

31+
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
3132
import org.graalvm.compiler.code.DataSection.Data;
3233
import org.graalvm.compiler.code.DataSection.Patches;
3334
import org.graalvm.compiler.core.common.type.CompressibleConstant;
@@ -50,8 +51,11 @@ public class SubstrateDataBuilder extends DataBuilder {
5051
@Override
5152
public Data createDataItem(Constant constant) {
5253
int size;
53-
if (constant instanceof VMConstant vmConstant) {
54-
assert constant instanceof JavaConstant && constant instanceof CompressibleConstant && constant instanceof TypedConstant : constant;
54+
if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
55+
size = FrameAccess.wordSize();
56+
return new ObjectData(size, size, methodPointerConstant);
57+
} else if (constant instanceof VMConstant vmConstant) {
58+
assert constant instanceof CompressibleConstant && constant instanceof TypedConstant : constant;
5559
return new ObjectData(vmConstant);
5660
} else if (JavaConstant.isNull(constant)) {
5761
if (SubstrateObjectConstant.isCompressed((JavaConstant) constant)) {
@@ -60,9 +64,8 @@ public Data createDataItem(Constant constant) {
6064
size = FrameAccess.uncompressedReferenceSize();
6165
}
6266
return createZeroData(size, size);
63-
} else if (constant instanceof SerializableConstant) {
64-
SerializableConstant s = (SerializableConstant) constant;
65-
return createSerializableData(s);
67+
} else if (constant instanceof SerializableConstant serializableConstant) {
68+
return createSerializableData(serializableConstant);
6669
} else {
6770
throw new JVMCIError(String.valueOf(constant));
6871
}
@@ -71,15 +74,19 @@ public Data createDataItem(Constant constant) {
7174
public static class ObjectData extends Data {
7275
private final VMConstant constant;
7376

77+
protected ObjectData(int alignment, int size, VMConstant constant) {
78+
super(alignment, size);
79+
this.constant = constant;
80+
}
81+
7482
protected ObjectData(VMConstant constant) {
75-
super(ConfigurationValues.getObjectLayout().getReferenceSize(), ConfigurationValues.getObjectLayout().getReferenceSize());
83+
this(ConfigurationValues.getObjectLayout().getReferenceSize(), ConfigurationValues.getObjectLayout().getReferenceSize(), constant);
7684
assert ((CompressibleConstant) constant).isCompressed() == ReferenceAccess.singleton()
7785
.haveCompressedReferences() : "Constant object references in compiled code must be compressed (base-relative)";
78-
this.constant = constant;
7986
}
8087

81-
public JavaConstant getConstant() {
82-
return (JavaConstant) constant;
88+
public VMConstant getConstant() {
89+
return constant;
8390
}
8491

8592
@Override
@@ -92,7 +99,7 @@ public static void emit(ByteBuffer buffer, Patches patches, int size, VMConstant
9299
if (size == Integer.BYTES) {
93100
buffer.putInt(0);
94101
} else if (size == Long.BYTES) {
95-
buffer.putLong(0L);
102+
buffer.putLong(0);
96103
} else {
97104
shouldNotReachHere("Unsupported object constant reference size: " + size);
98105
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import java.util.concurrent.ConcurrentMap;
4040
import java.util.concurrent.ForkJoinPool;
4141

42+
import com.oracle.svm.core.graal.code.SubstrateDataBuilder;
4243
import org.graalvm.collections.EconomicMap;
4344
import org.graalvm.compiler.api.replacements.Fold;
4445
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
@@ -122,7 +123,6 @@
122123
import com.oracle.svm.core.graal.phases.OptimizeExceptionPathsPhase;
123124
import com.oracle.svm.core.heap.RestrictHeapAccess;
124125
import com.oracle.svm.core.heap.RestrictHeapAccessCallees;
125-
import com.oracle.svm.core.meta.MethodPointer;
126126
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
127127
import com.oracle.svm.core.util.InterruptImageBuilding;
128128
import com.oracle.svm.core.util.VMError;
@@ -151,6 +151,7 @@
151151
import jdk.vm.ci.meta.MetaAccessProvider;
152152
import jdk.vm.ci.meta.ResolvedJavaMethod;
153153
import jdk.vm.ci.meta.VMConstant;
154+
import org.graalvm.nativeimage.Platform;
154155

155156
public class CompileQueue {
156157

@@ -1368,15 +1369,29 @@ protected void removeDeoptTargetOptimizations(LIRSuites lirSuites) {
13681369
DeoptimizationUtils.removeDeoptTargetOptimizations(lirSuites);
13691370
}
13701371

1372+
private void ensureCompiledForMethodPointerConstant(HostedMethod method, CompileReason reason, SubstrateMethodPointerConstant methodPointerConstant) {
1373+
HostedMethod referencedMethod = (HostedMethod) methodPointerConstant.pointer().getMethod();
1374+
ensureCompiled(referencedMethod, new MethodPointerConstantReason(method, referencedMethod, reason));
1375+
}
1376+
13711377
protected final void ensureCompiledForMethodPointerConstants(HostedMethod method, CompileReason reason, CompilationResult result) {
13721378
for (DataPatch dataPatch : result.getDataPatches()) {
13731379
Reference reference = dataPatch.reference;
1374-
if (reference instanceof ConstantReference) {
1375-
VMConstant constant = ((ConstantReference) reference).getConstant();
1376-
if (constant instanceof SubstrateMethodPointerConstant) {
1377-
MethodPointer pointer = ((SubstrateMethodPointerConstant) constant).pointer();
1378-
HostedMethod referencedMethod = (HostedMethod) pointer.getMethod();
1379-
ensureCompiled(referencedMethod, new MethodPointerConstantReason(method, referencedMethod, reason));
1380+
if (reference instanceof ConstantReference constantReference) {
1381+
VMConstant vmConstant = constantReference.getConstant();
1382+
if (vmConstant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
1383+
ensureCompiledForMethodPointerConstant(method, reason, methodPointerConstant);
1384+
}
1385+
}
1386+
}
1387+
1388+
for (DataSection.Data data : result.getDataSection()) {
1389+
if (data instanceof SubstrateDataBuilder.ObjectData objectData) {
1390+
VMConstant vmConstant = objectData.getConstant();
1391+
if (vmConstant instanceof SubstrateMethodPointerConstant methodPointerConstant) {
1392+
/* [GR-43389] Only reachable with ld64 workaround on */
1393+
VMError.guarantee(Platform.includedIn(Platform.DARWIN_AMD64.class));
1394+
ensureCompiledForMethodPointerConstant(method, reason, methodPointerConstant);
13801395
}
13811396
}
13821397
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) {
126126
VMConstant constant = ((ConstantReference) ref).getConstant();
127127
Object relocVal = ref;
128128
if (constant instanceof SubstrateMethodPointerConstant) {
129+
VMError.guarantee(!Platform.includedIn(Platform.DARWIN_AMD64.class), "[GR-43389] method pointer relocations should not be inlined.");
129130
MethodPointer pointer = ((SubstrateMethodPointerConstant) constant).pointer();
130131
HostedMethod hMethod = (HostedMethod) pointer.getMethod();
131132
VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod);

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public void layoutConstants() {
187187
CompilationResult compilation = pair.getRight();
188188
for (DataSection.Data data : compilation.getDataSection()) {
189189
if (data instanceof SubstrateDataBuilder.ObjectData) {
190-
JavaConstant constant = ((SubstrateDataBuilder.ObjectData) data).getConstant();
190+
VMConstant constant = ((SubstrateDataBuilder.ObjectData) data).getConstant();
191191
constantReasons.put(constant, compilation.getName());
192192
}
193193
}
@@ -207,7 +207,7 @@ public void layoutConstants() {
207207
public void addConstantsToHeap() {
208208
for (DataSection.Data data : dataSection) {
209209
if (data instanceof SubstrateDataBuilder.ObjectData) {
210-
JavaConstant constant = ((SubstrateDataBuilder.ObjectData) data).getConstant();
210+
VMConstant constant = ((SubstrateDataBuilder.ObjectData) data).getConstant();
211211
addConstantToHeap(constant, NativeImageHeap.HeapInclusionReason.DataSection);
212212
}
213213
}
@@ -585,7 +585,7 @@ protected boolean verifyMethods(HostedUniverse hUniverse, ForkJoinPool threadPoo
585585
public void writeConstants(NativeImageHeapWriter writer, RelocatableBuffer buffer) {
586586
ByteBuffer bb = buffer.getByteBuffer();
587587
dataSection.buildDataSection(bb, (position, constant) -> {
588-
writer.writeReference(buffer, position, (JavaConstant) constant, "VMConstant: " + constant);
588+
writer.writeReference(buffer, position, constant, "VMConstant: " + constant);
589589
});
590590
}
591591

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,15 @@
3131
import java.lang.reflect.Modifier;
3232
import java.nio.ByteBuffer;
3333

34+
import com.oracle.svm.core.meta.SubstrateMethodPointerConstant;
35+
import jdk.vm.ci.meta.Constant;
3436
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
3537
import org.graalvm.compiler.core.common.CompressEncoding;
3638
import org.graalvm.compiler.core.common.NumUtil;
3739
import org.graalvm.compiler.debug.DebugContext;
3840
import org.graalvm.compiler.debug.Indent;
3941
import org.graalvm.nativeimage.ImageSingletons;
42+
import org.graalvm.nativeimage.Platform;
4043
import org.graalvm.nativeimage.c.function.CFunctionPointer;
4144
import org.graalvm.nativeimage.c.function.RelocatedPointer;
4245
import org.graalvm.word.WordBase;
@@ -165,10 +168,16 @@ private void write(RelocatableBuffer buffer, int index, JavaConstant con, Object
165168
private final boolean useHeapBase = NativeImageHeap.useHeapBase();
166169
private final CompressEncoding compressEncoding = ImageSingletons.lookup(CompressEncoding.class);
167170

168-
void writeReference(RelocatableBuffer buffer, int index, JavaConstant target, Object reason) {
169-
assert !(heap.hMetaAccess.isInstanceOf(target, WordBase.class)) : "word values are not references";
171+
void writeReference(RelocatableBuffer buffer, int index, Constant constant, Object reason) {
170172
mustBeReferenceAligned(index);
171-
if (target.isNonNull()) {
173+
174+
if (constant instanceof JavaConstant target) {
175+
assert !(heap.hMetaAccess.isInstanceOf(target, WordBase.class)) : "word values are not references";
176+
177+
if (target.isNull()) {
178+
return;
179+
}
180+
172181
ObjectInfo targetInfo = heap.getConstantInfo(target);
173182
verifyTargetDidNotChange(target, reason, targetInfo);
174183
if (useHeapBase) {
@@ -177,6 +186,9 @@ void writeReference(RelocatableBuffer buffer, int index, JavaConstant target, Ob
177186
} else {
178187
addDirectRelocationWithoutAddend(buffer, index, referenceSize(), target);
179188
}
189+
} else {
190+
assert Platform.includedIn(Platform.DARWIN_AMD64.class) : "[GR-43389] Workaround for ld64 bug that does not allow direct8 relocations in .text on amd64";
191+
buffer.addRelocationWithoutAddend(index, ObjectFile.RelocationKind.DIRECT_8, ((SubstrateMethodPointerConstant) constant).pointer());
180192
}
181193
}
182194

0 commit comments

Comments
 (0)