diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java index 8c30d708f4a6..49c7d73453bf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java @@ -37,7 +37,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.oracle.svm.hosted.c.libc.HostedLibCBase; import org.graalvm.compiler.options.Option; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -57,6 +56,7 @@ import com.oracle.svm.hosted.c.CGlobalDataFeature; import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.c.codegen.CCompilerInvoker; +import com.oracle.svm.hosted.c.libc.HostedLibCBase; public abstract class CCLinkerInvocation implements LinkerInvocation { @@ -258,34 +258,28 @@ private static class BinutilsCCLinkerInvocation extends CCLinkerInvocation { additionalPreOptions.add("-Wl,--gc-sections"); } - /* - * On Linux we use --dynamic-list to ensure only our defined entrypoints end up as - * global symbols in the dynamic symbol table of the image. However, when compiling a - * static image these are not needed, and some linkers interpret them wrong, creating a - * corrupt binary. - */ - if (!SubstrateOptions.StaticExecutable.getValue()) { - try { - StringBuilder exportedSymbols = new StringBuilder(); - exportedSymbols.append("{\n"); - for (String symbol : getImageSymbols(true)) { - exportedSymbols.append('\"').append(symbol).append("\";\n"); - } - exportedSymbols.append("};"); - Path exportedSymbolsPath = nativeLibs.tempDirectory.resolve("exported_symbols.list"); - Files.write(exportedSymbolsPath, Collections.singleton(exportedSymbols.toString())); - additionalPreOptions.add("-Wl,--dynamic-list"); - additionalPreOptions.add("-Wl," + exportedSymbolsPath.toAbsolutePath()); - - // Drop global symbols in linked static libraries: not covered by --dynamic-list - additionalPreOptions.add("-Wl,--exclude-libs,ALL"); - - additionalPreOptions.addAll(HostedLibCBase.singleton().getAdditionalLinkerOptions(imageKind)); - } catch (IOException e) { - VMError.shouldNotReachHere(); + /* Use --version-script to control the visibility of image symbols. */ + try { + StringBuilder exportedSymbols = new StringBuilder(); + exportedSymbols.append("{\n"); + /* Only exported symbols are global ... */ + exportedSymbols.append("global:\n"); + for (String symbol : getImageSymbols(true)) { + exportedSymbols.append('\"').append(symbol).append("\";\n"); } + /* ... everything else is local. */ + exportedSymbols.append("local: *;\n"); + exportedSymbols.append("};"); + + Path exportedSymbolsPath = nativeLibs.tempDirectory.resolve("exported_symbols.list"); + Files.write(exportedSymbolsPath, Collections.singleton(exportedSymbols.toString())); + additionalPreOptions.add("-Wl,--version-script," + exportedSymbolsPath.toAbsolutePath()); + } catch (IOException e) { + VMError.shouldNotReachHere(); } + additionalPreOptions.addAll(HostedLibCBase.singleton().getAdditionalLinkerOptions(imageKind)); + if (SubstrateOptions.DeleteLocalSymbols.getValue()) { additionalPreOptions.add("-Wl,-x"); } @@ -300,6 +294,8 @@ String getSymbolName(ObjectFile.Symbol symbol) { protected void setOutputKind(List cmd) { switch (imageKind) { case EXECUTABLE: + /* Export global symbols. */ + cmd.add("-Wl,--export-dynamic"); break; case STATIC_EXECUTABLE: if (!staticExecWithDynamicallyLinkLibC) {