Skip to content

Commit f63610c

Browse files
author
Christian Wimmer
committed
Make internal symbols local
1 parent 8f31fdd commit f63610c

File tree

8 files changed

+83
-49
lines changed

8 files changed

+83
-49
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ protected void onValueUpdate(EconomicMap<OptionKey<?>, Object> values, String ol
379379
* functions makes it incoherent with the executable.
380380
*/
381381
RemoveUnusedSymbols.update(values, false);
382+
InternalSymbolsAreGlobal.update(values, true);
382383
/*
383384
* The LLVM backend doesn't support speculative execution attack mitigation
384385
*/
@@ -399,6 +400,10 @@ public static boolean useLLVMBackend() {
399400
public static final HostedOptionKey<Boolean> RemoveUnusedSymbols = new HostedOptionKey<>(false);
400401
@Option(help = "Use linker option to remove all local symbols from image.")//
401402
public static final HostedOptionKey<Boolean> DeleteLocalSymbols = new HostedOptionKey<>(true);
403+
@Option(help = "Compatibility option to make symbols used for the image heap global. " +
404+
"Using global symbols is problematic for shared libraries because the loader implicitly changes the value when the symbol is already defined in the executable loading the library. " +
405+
"Setting this option to true preserves the broken behavior of old Native Image versions.")//
406+
public static final HostedOptionKey<Boolean> InternalSymbolsAreGlobal = new HostedOptionKey<>(true);
402407

403408
@Option(help = "Common prefix used by method symbols in image.")//
404409
public static final HostedOptionKey<String> ImageSymbolsPrefix = new HostedOptionKey<>("");

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/VM.java

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -27,45 +27,22 @@
2727
import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
2828
import org.graalvm.nativeimage.Platform;
2929
import org.graalvm.nativeimage.Platforms;
30-
import org.graalvm.nativeimage.c.type.CCharPointer;
3130

32-
import com.oracle.svm.core.c.CGlobalData;
33-
import com.oracle.svm.core.c.CGlobalDataFactory;
34-
import com.oracle.svm.core.util.Utf8;
3531
import com.oracle.svm.core.util.VMError;
3632

3733
public final class VM {
38-
@Platforms(Platform.HOSTED_ONLY.class) //
39-
public static final String valueSeparator = "=";
40-
@Platforms(Platform.HOSTED_ONLY.class) //
41-
private static final String versionValue = getVersionValue();
34+
public static final String VERSION = buildVersion();
4235

4336
@Platforms(Platform.HOSTED_ONLY.class)
44-
private static String getVersionValue() {
37+
private static String buildVersion() {
4538
String version = System.getProperty("org.graalvm.version");
4639
VMError.guarantee(version != null);
47-
version = VM.class.getName() + valueSeparator + "GraalVM " + version;
40+
version = "GraalVM " + version;
4841
version += " Java " + JavaVersionUtil.JAVA_SPEC;
4942
String config = System.getProperty("org.graalvm.config", "");
5043
if (!config.isEmpty()) {
5144
version += " " + config;
5245
}
5346
return version;
5447
}
55-
56-
private static final String VERSION_INFO_SYMBOL_NAME = "__svm_version_info";
57-
private static final CGlobalData<CCharPointer> VERSION_INFO = CGlobalDataFactory.createCString(versionValue, VERSION_INFO_SYMBOL_NAME);
58-
59-
private static final int versionValueHash = versionValue.hashCode();
60-
61-
public static String getVersion() {
62-
CCharPointer versionInfoBytes = VERSION_INFO.get();
63-
String version = Utf8.utf8ToString(versionInfoBytes);
64-
if (version == null || version.hashCode() != versionValueHash) {
65-
VMError.shouldNotReachHere("HashCode mismatch for " + VERSION_INFO_SYMBOL_NAME +
66-
": actual " + (version == null ? "null" : String.valueOf(version.hashCode())) +
67-
" (expected " + versionValueHash + ")");
68-
}
69-
return SubstrateUtil.split(version, valueSeparator)[1];
70-
}
7148
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public final class CGlobalDataInfo {
4242
private final CGlobalDataImpl<?> data;
4343
private final boolean isSymbolReference;
4444

45+
private boolean isGlobalSymbol;
46+
private boolean isHiddenSymbol;
4547
private int offset = -1;
4648

4749
/** Cache until writing the image in case the {@link Supplier} is costly or has side-effects. */
@@ -71,6 +73,23 @@ public int getOffset() {
7173
return offset;
7274
}
7375

76+
public void makeGlobalSymbol() {
77+
VMError.guarantee(!isSymbolReference && data.symbolName != null, "Cannot change the local/global status of a symbol reference");
78+
isGlobalSymbol = true;
79+
}
80+
81+
public boolean isGlobalSymbol() {
82+
return isGlobalSymbol;
83+
}
84+
85+
public void makeHiddenSymbol() {
86+
isHiddenSymbol = true;
87+
}
88+
89+
public boolean isHiddenSymbol() {
90+
return isHiddenSymbol;
91+
}
92+
7493
public boolean isSymbolReference() {
7594
return isSymbolReference;
7695
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SystemPropertiesSupport.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ protected SystemPropertiesSupport() {
102102

103103
initializeProperty("java.vm.name", "Substrate VM");
104104
initializeProperty("java.vm.vendor", "Oracle Corporation");
105+
initializeProperty("java.vm.version", VM.VERSION);
105106
initializeProperty("java.vendor", "Oracle Corporation");
106107
initializeProperty("java.vendor.url", "https://www.graalvm.org/");
107108

@@ -126,7 +127,6 @@ protected SystemPropertiesSupport() {
126127
lazyRuntimeValues.put("user.dir", this::userDir);
127128
lazyRuntimeValues.put("java.io.tmpdir", this::tmpDir);
128129
lazyRuntimeValues.put("os.version", this::osVersionValue);
129-
lazyRuntimeValues.put("java.vm.version", VM::getVersion);
130130

131131
String targetName = System.getProperty("svm.targetName");
132132
if (targetName != null) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/VMFeature.java

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
*/
2525
package com.oracle.svm.hosted;
2626

27-
import java.lang.reflect.Field;
2827
import java.nio.file.Path;
2928
import java.nio.file.Paths;
3029
import java.util.stream.Collectors;
@@ -41,7 +40,6 @@
4140
import com.oracle.svm.core.c.CGlobalData;
4241
import com.oracle.svm.core.c.CGlobalDataFactory;
4342
import com.oracle.svm.core.c.libc.LibCBase;
44-
import com.oracle.svm.core.util.VMError;
4543
import com.oracle.svm.hosted.c.CGlobalDataFeature;
4644
import com.oracle.svm.hosted.c.NativeLibraries;
4745
import com.oracle.svm.hosted.c.codegen.CCompilerInvoker;
@@ -51,6 +49,8 @@ public class VMFeature implements Feature {
5149

5250
private NativeLibraries nativeLibraries;
5351
private static final String STATIC_BINARY_MARKER_SYMBOL_NAME = "__svm_vm_is_static_binary";
52+
private static final String VERSION_INFO_SYMBOL_NAME = "__svm_version_info";
53+
private static final String valueSeparator = "=";
5454

5555
@Override
5656
public void beforeAnalysis(BeforeAnalysisAccess a) {
@@ -64,19 +64,13 @@ public void beforeAnalysis(BeforeAnalysisAccess a) {
6464
}
6565

6666
FeatureImpl.BeforeAnalysisAccessImpl access = (FeatureImpl.BeforeAnalysisAccessImpl) a;
67-
String fieldName = "VERSION_INFO";
68-
try {
69-
Field declaredField = VM.class.getDeclaredField(fieldName);
70-
access.registerAsRead(declaredField);
71-
} catch (NoSuchFieldException e) {
72-
VMError.shouldNotReachHere(VM.class.getName() + " should have field " + fieldName);
73-
}
74-
7567
nativeLibraries = access.getNativeLibraries();
7668
}
7769

7870
@Override
7971
public void afterAnalysis(AfterAnalysisAccess access) {
72+
CGlobalDataFeature.singleton().registerWithGlobalSymbol(CGlobalDataFactory.createCString(VM.class.getName() + valueSeparator + VM.VERSION, VERSION_INFO_SYMBOL_NAME));
73+
8074
addCGlobalDataString("Target.Platform", ImageSingletons.lookup(Platform.class).getClass().getName());
8175
addCGlobalDataString("Target.LibC", ImageSingletons.lookup(LibCBase.class).getClass().getName());
8276

@@ -94,12 +88,12 @@ public void afterAnalysis(AfterAnalysisAccess access) {
9488
}
9589

9690
CGlobalData<PointerBase> isStaticBinaryMarker = CGlobalDataFactory.createWord(WordFactory.unsigned(SubstrateOptions.StaticExecutable.getValue() ? 1 : 0), STATIC_BINARY_MARKER_SYMBOL_NAME);
97-
CGlobalDataFeature.singleton().registerAsAccessedOrGet(isStaticBinaryMarker);
91+
CGlobalDataFeature.singleton().registerWithGlobalHiddenSymbol(isStaticBinaryMarker);
9892
}
9993

10094
private static void addCGlobalDataString(String infoType, String content) {
101-
String data = VM.class.getName() + "." + infoType + VM.valueSeparator + content;
95+
String data = VM.class.getName() + "." + infoType + valueSeparator + content;
10296
String symbolName = "__svm_vm_" + infoType.toLowerCase().replace(".", "_");
103-
CGlobalDataFeature.singleton().registerAsAccessedOrGet(CGlobalDataFactory.createCString(data, symbolName));
97+
CGlobalDataFeature.singleton().registerWithGlobalSymbol(CGlobalDataFactory.createCString(data, symbolName));
10498
}
10599
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232
import java.nio.ByteBuffer;
3333
import java.util.Map;
3434
import java.util.Map.Entry;
35+
import java.util.Set;
3536
import java.util.concurrent.ConcurrentHashMap;
36-
import java.util.function.BiFunction;
37+
import java.util.stream.Collectors;
3738
import java.util.stream.IntStream;
3839

3940
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
@@ -204,6 +205,36 @@ public CGlobalDataInfo registerAsAccessedOrGet(CGlobalData<?> obj) {
204205
});
205206
}
206207

208+
/**
209+
* Makes the provided object available in the binary as a global symbol
210+
*
211+
* Warning: Global symbols are affected by linking and loading rules that are OS dependent. So
212+
* accessing a global symbol content at run time using the symbol name could return a different
213+
* content than the one provided at build time. This happens for example on Linux when a shared
214+
* library is loaded and the main executable already defines a symbol with the same name.
215+
*/
216+
public void registerWithGlobalSymbol(CGlobalData<?> obj) {
217+
registerWithGlobalSymbolImpl(obj);
218+
}
219+
220+
/**
221+
* Same as {@link #registerWithGlobalSymbol(CGlobalData)} but hides the provided object so that
222+
* it will not show up in the dynamic symbol table of the final image.
223+
*/
224+
public void registerWithGlobalHiddenSymbol(CGlobalData<?> obj) {
225+
registerWithGlobalSymbolImpl(obj).makeHiddenSymbol();
226+
}
227+
228+
private CGlobalDataInfo registerWithGlobalSymbolImpl(CGlobalData<?> obj) {
229+
CGlobalDataInfo info = registerAsAccessedOrGet(obj);
230+
info.makeGlobalSymbol();
231+
return info;
232+
}
233+
234+
public Set<String> getGlobalHiddenSymbols() {
235+
return map.entrySet().stream().filter(entry -> entry.getValue().isGlobalSymbol() && entry.getValue().isHiddenSymbol()).map(entry -> entry.getKey().symbolName).collect(Collectors.toSet());
236+
}
237+
207238
private Object replaceObject(Object obj) {
208239
if (obj instanceof CGlobalDataImpl<?>) {
209240
registerAsAccessedOrGet((CGlobalData<?>) obj);
@@ -250,7 +281,11 @@ public int getSize() {
250281
return totalSize;
251282
}
252283

253-
public void writeData(RelocatableBuffer buffer, BiFunction<Integer, String, ?> createSymbol, BiFunction<Integer, String, ?> createSymbolReference) {
284+
public interface SymbolConsumer {
285+
void apply(int offset, String symbolName, boolean isGlobalSymbol);
286+
}
287+
288+
public void writeData(RelocatableBuffer buffer, SymbolConsumer createSymbol, SymbolConsumer createSymbolReference) {
254289
assert isLayouted() : "Not layouted yet";
255290
ByteBuffer bufferBytes = buffer.getByteBuffer();
256291
int start = bufferBytes.position();
@@ -263,10 +298,10 @@ public void writeData(RelocatableBuffer buffer, BiFunction<Integer, String, ?> c
263298
}
264299
CGlobalDataImpl<?> data = info.getData();
265300
if (data.symbolName != null && !info.isSymbolReference()) {
266-
createSymbol.apply(info.getOffset(), data.symbolName);
301+
createSymbol.apply(info.getOffset(), data.symbolName, info.isGlobalSymbol());
267302
}
268303
if (data.nonConstant) {
269-
createSymbolReference.apply(info.getOffset(), data.symbolName);
304+
createSymbolReference.apply(info.getOffset(), data.symbolName, info.isGlobalSymbol());
270305
}
271306
}
272307
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.List;
3030
import java.util.Map;
3131
import java.util.Map.Entry;
32+
import java.util.Set;
3233
import java.util.concurrent.ForkJoinPool;
3334
import java.util.stream.Collectors;
3435
import java.util.stream.Stream;
@@ -48,6 +49,7 @@
4849
import com.oracle.svm.core.config.ConfigurationValues;
4950
import com.oracle.svm.core.meta.SubstrateObjectConstant;
5051
import com.oracle.svm.core.util.VMError;
52+
import com.oracle.svm.hosted.c.CGlobalDataFeature;
5153
import com.oracle.svm.hosted.code.HostedImageHeapConstantPatch;
5254
import com.oracle.svm.hosted.code.HostedPatcher;
5355
import com.oracle.svm.hosted.image.NativeImage.NativeTextSectionImpl;
@@ -244,7 +246,8 @@ protected void defineMethodSymbol(String name, boolean global, ObjectFile.Elemen
244246
public List<ObjectFile.Symbol> getSymbols(ObjectFile objectFile, boolean onlyGlobal) {
245247
Stream<ObjectFile.Symbol> stream = StreamSupport.stream(objectFile.getSymbolTable().spliterator(), false);
246248
if (onlyGlobal) {
247-
stream = stream.filter(ObjectFile.Symbol::isGlobal);
249+
Set<String> globalHiddenSymbols = CGlobalDataFeature.singleton().getGlobalHiddenSymbols();
250+
stream = stream.filter(symbol -> symbol.isGlobal() && !globalHiddenSymbols.contains(symbol.getName()));
248251
}
249252
return stream.filter(ObjectFile.Symbol::isDefined).collect(Collectors.toList());
250253
}

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ private boolean shouldWriteHeader(HostedMethod method) {
380380
}
381381

382382
private ObjectFile.Symbol defineDataSymbol(String name, Element section, long position) {
383-
return objectFile.createDefinedSymbol(name, section, position, wordSize, false, true);
383+
return objectFile.createDefinedSymbol(name, section, position, wordSize, false, SubstrateOptions.InternalSymbolsAreGlobal.getValue());
384384
}
385385

386386
private ObjectFile.Symbol defineRelocationForSymbol(String name, long position) {
@@ -429,7 +429,7 @@ public void build(String imageName, DebugContext debug) {
429429

430430
// Define symbols for the sections.
431431
objectFile.createDefinedSymbol(textSection.getName(), textSection, 0, 0, false, false);
432-
objectFile.createDefinedSymbol("__svm_text_end", textSection, textSectionSize, 0, false, true);
432+
objectFile.createDefinedSymbol("__svm_text_end", textSection, textSectionSize, 0, false, SubstrateOptions.InternalSymbolsAreGlobal.getValue());
433433
objectFile.createDefinedSymbol(roDataSection.getName(), roDataSection, 0, 0, false, false);
434434
objectFile.createDefinedSymbol(rwDataSection.getName(), rwDataSection, 0, 0, false, false);
435435

@@ -441,8 +441,9 @@ public void build(String imageName, DebugContext debug) {
441441
codeCache.writeConstants(writer, roDataBuffer);
442442
// - Non-heap global data goes at the beginning of the read-write data section.
443443
cGlobals.writeData(rwDataBuffer,
444-
(offset, symbolName) -> defineDataSymbol(symbolName, rwDataSection, offset + RWDATA_CGLOBALS_PARTITION_OFFSET),
445-
(offset, symbolName) -> defineRelocationForSymbol(symbolName, offset));
444+
(offset, symbolName, isGlobalSymbol) -> objectFile.createDefinedSymbol(symbolName, rwDataSection, offset + RWDATA_CGLOBALS_PARTITION_OFFSET, wordSize, false,
445+
isGlobalSymbol || SubstrateOptions.InternalSymbolsAreGlobal.getValue()),
446+
(offset, symbolName, isGlobalSymbol) -> defineRelocationForSymbol(symbolName, offset));
446447
defineDataSymbol(CGlobalDataInfo.CGLOBALDATA_BASE_SYMBOL_NAME, rwDataSection, RWDATA_CGLOBALS_PARTITION_OFFSET);
447448

448449
/*

0 commit comments

Comments
 (0)