From 723df10272610ffceda1ac9490390e75f30da6da Mon Sep 17 00:00:00 2001 From: Dominik Mascherbauer Date: Mon, 8 Sep 2025 16:01:55 +0200 Subject: [PATCH] Set common-page-size for the linker invocation to ensure proper object file alignment after linking. --- .../svm/hosted/image/CCLinkerInvocation.java | 14 ++++++ .../NativeImageDebugInfoStripFeature.java | 48 ++++++------------- 2 files changed, 28 insertions(+), 34 deletions(-) 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 82331bbef008..6c9602e7938e 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 @@ -268,6 +268,20 @@ private static class BinutilsCCLinkerInvocation extends CCLinkerInvocation { additionalPreOptions.add("-z"); additionalPreOptions.add(SpawnIsolates.getValue() ? "text" : "notext"); + /* + * Make the linker aware of the page size used for aligning the native image object file + * sections. This makes sure that the resulting object file is always properly aligned, + * otherwise it would cause an error in ld-linux (glibc older than 2.35) if a specific + * linker version is involved (e.g. GNU binutils ld 2.38). + * + * In older glibc versions this is caused by a stricter page alignment check. Page + * alignment is checked against the alignment that comes from the linker instead of the + * system page size. This allows technically incorrect ELF object files to run on newer + * versions. + */ + additionalPreOptions.add("-z"); + additionalPreOptions.add("common-page-size=" + SubstrateOptions.getPageSize()); + if (SubstrateOptions.RemoveUnusedSymbols.getValue()) { /* Perform garbage collection of unused input sections. */ additionalPreOptions.add("-Wl,--gc-sections"); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoStripFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoStripFeature.java index b91949b52b42..4741dbde0c14 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoStripFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoStripFeature.java @@ -53,12 +53,7 @@ public class NativeImageDebugInfoStripFeature implements InternalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { - /* - * Make sure this feature always runs for ELF object files to fix the object file's - * alignment with objcopy. This is a temporary workaround; a proper fix will be provided - * with GR-68594. - */ - return SubstrateOptions.StripDebugInfo.getValue() || ObjectFile.getNativeFormat() == ObjectFile.Format.ELF; + return SubstrateOptions.StripDebugInfo.getValue(); } @SuppressWarnings("try") @@ -117,35 +112,20 @@ private static boolean stripLinux(AfterImageWriteAccessImpl accessImpl) { try { Path outputDirectory = imagePath.getParent(); String imageFilePath = outputDirectory.resolve(imageName).toString(); - if (SubstrateOptions.StripDebugInfo.getValue()) { - if (SubstrateOptions.useDebugInfoGeneration()) { - /* Generate a separate debug file before stripping the executable. */ - String debugInfoName = imageName + debugExtension; - Path debugInfoFilePath = outputDirectory.resolve(debugInfoName); - FileUtils.executeCommand(objcopyExe, "--only-keep-debug", imageFilePath, debugInfoFilePath.toString()); - BuildArtifacts.singleton().add(ArtifactType.DEBUG_INFO, debugInfoFilePath); - FileUtils.executeCommand(objcopyExe, "--add-gnu-debuglink=" + debugInfoFilePath, imageFilePath); - } - if (SubstrateOptions.DeleteLocalSymbols.getValue()) { - /* Strip debug info and local symbols. */ - FileUtils.executeCommand(objcopyExe, "--strip-all", imageFilePath); - } else { - /* Strip debug info only. */ - FileUtils.executeCommand(objcopyExe, "--strip-debug", imageFilePath); - } + if (SubstrateOptions.useDebugInfoGeneration()) { + /* Generate a separate debug file before stripping the executable. */ + String debugInfoName = imageName + debugExtension; + Path debugInfoFilePath = outputDirectory.resolve(debugInfoName); + FileUtils.executeCommand(objcopyExe, "--only-keep-debug", imageFilePath, debugInfoFilePath.toString()); + BuildArtifacts.singleton().add(ArtifactType.DEBUG_INFO, debugInfoFilePath); + FileUtils.executeCommand(objcopyExe, "--add-gnu-debuglink=" + debugInfoFilePath, imageFilePath); + } + if (SubstrateOptions.DeleteLocalSymbols.getValue()) { + /* Strip debug info and local symbols. */ + FileUtils.executeCommand(objcopyExe, "--strip-all", imageFilePath); } else { - /* - * Make sure the object file is properly aligned. This step creates a temporary - * file and then destructively renames it to the original image file name. In - * effect, the original native image object file is copied and replaced with the - * output of objcopy. - * - * This is a temporary workaround; a proper fix will be provided with GR-68594. - */ - FileUtils.executeCommand(objcopyExe, imageFilePath); - - /* Nothing was actually stripped here. */ - return false; + /* Strip debug info only. */ + FileUtils.executeCommand(objcopyExe, "--strip-debug", imageFilePath); } return true; } catch (IOException e) {