This is an automated email from the ASF dual-hosted git repository. shaojunwang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-java-tee-sdk.git
commit cee5dd4f97f84b9014cf10b0919577077d608062 Author: cengfeng.lzy <[email protected]> AuthorDate: Thu Mar 31 10:24:28 2022 +0800 [Enc] Support static linking with musl Summary: Native-image doesn't suport compiling musl based static library. We loose this restriction in this commit. But we only need native-image to complie the relocatable file (the .o file), and the static linking is done by ourselves. Test Plan: all tests pass Reviewers: lei.yul, jeffery.wsj, sanhong.lsh Issue: https://aone.alibaba-inc.com/task/41423615 CR: https://code.aone.alibaba-inc.com/java-tee/JavaEnclave/codereview/8660164 --- sdk/enclave/pom.xml | 44 +++------------- .../enclave/EnclaveFeature.java | 35 +++++++++++++ .../enclave/system/EnclaveMuslLibcFeature.java | 35 +++++++++++++ .../enclave/AroundNativeTest.java | 49 ------------------ .../enclave/NativeImageTest.java | 59 ++++++++++++++++++---- 5 files changed, 128 insertions(+), 94 deletions(-) diff --git a/sdk/enclave/pom.xml b/sdk/enclave/pom.xml index 8b66556..eaf153d 100644 --- a/sdk/enclave/pom.xml +++ b/sdk/enclave/pom.xml @@ -74,9 +74,13 @@ <target>11</target> <compilerArgs> <arg>--add-modules</arg> - <arg>jdk.internal.vm.ci</arg> + <arg>jdk.internal.vm.ci,jdk.internal.vm.compiler</arg> <arg>--add-exports</arg> <arg>jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED</arg> + <arg>--add-exports</arg> + <arg>jdk.internal.vm.compiler/org.graalvm.compiler.serviceprovider=ALL-UNNAMED</arg> + <arg>--add-exports</arg> + <arg>jdk.internal.vm.compiler/org.graalvm.compiler.options=ALL-UNNAMED</arg> </compilerArgs> <!--OptionProcessor can automatically generate OptionDescriptor classes at javac time--> <annotationProcessorPaths> @@ -115,9 +119,11 @@ <doclint>none</doclint> <additionalJOptions> <additionalJOption>--add-modules</additionalJOption> - <additionalJOption>jdk.internal.vm.ci</additionalJOption> + <additionalJOption>jdk.internal.vm.ci,jdk.internal.vm.compiler</additionalJOption> <additionalJOption>--add-exports</additionalJOption> <additionalJOption>jdk.internal.vm.ci/jdk.vm.ci.meta=ALL-UNNAMED</additionalJOption> + <additionalJOption>--add-exports</additionalJOption> + <additionalJOption>jdk.internal.vm.compiler/org.graalvm.compiler.serviceprovider=ALL-UNNAMED</additionalJOption> </additionalJOptions> </configuration> <version>3.2.0</version> @@ -155,44 +161,10 @@ </execution> </executions> </plugin> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>exec-maven-plugin</artifactId> - <version>3.0.0</version> - <executions> - <execution> - <id>preTest</id> - <phase>test-compile</phase> - <goals> - <goal>java</goal> - </goals> - <configuration> - <mainClass>com.alibaba.confidentialcomputing.enclave.AroundNativeTest$PreTest</mainClass> - <classpathScope>test</classpathScope> - </configuration> - </execution> - <execution> - <id>postTest</id> - <phase>test</phase> - <goals> - <goal>java</goal> - </goals> - <configuration> - <mainClass>com.alibaba.confidentialcomputing.enclave.AroundNativeTest$PostTest</mainClass> - <classpathScope>test</classpathScope> - </configuration> - </execution> - </executions> - </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> - <configuration> - <environmentVariables> - <LD_LIBRARY_PATH>/tmp/javaenclavetest-native-libs</LD_LIBRARY_PATH> - </environmentVariables> - </configuration> </plugin> </plugins> </build> diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveFeature.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveFeature.java index 2c6a346..8875700 100644 --- a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveFeature.java +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/EnclaveFeature.java @@ -7,10 +7,12 @@ import com.alibaba.confidentialcomputing.enclave.framework.LoadServiceInvoker; import com.alibaba.confidentialcomputing.enclave.framework.ServiceMethodInvoker; import com.alibaba.confidentialcomputing.enclave.framework.UnloadServiceInvoker; import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.c.libc.TemporaryBuildDirectoryProvider; import com.oracle.svm.core.jdk.resources.NativeImageResourceFileSystemUtil; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl; import com.oracle.svm.hosted.ImageClassLoader; +import com.oracle.svm.hosted.NativeImageGenerator; import com.oracle.svm.hosted.ServiceLoaderFeature; import com.oracle.svm.reflect.hosted.ReflectionFeature; import com.oracle.svm.reflect.serialize.hosted.SerializationFeature; @@ -27,6 +29,12 @@ import java.io.InputStreamReader; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.charset.StandardCharsets; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardCopyOption; +import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -96,6 +104,33 @@ public class EnclaveFeature implements Feature { } } + /** + * Copy the relocatable file and header file from temporary directory to output path. + */ + @Override + public void afterImageWrite(AfterImageWriteAccess access) { + FeatureImpl.AfterImageWriteAccessImpl a = (FeatureImpl.AfterImageWriteAccessImpl) access; + Path outputDirectory = NativeImageGenerator.generatedFiles(a.getUniverse().getBigBang().getOptions()); + Path tempDirectory = ImageSingletons.lookup(TemporaryBuildDirectoryProvider.class).getTemporaryBuildDirectory(); + try { + if (Files.notExists(outputDirectory)) { + Files.createDirectory(outputDirectory); + } + Files.walkFileTree(tempDirectory, new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String fileName = file.getFileName().toString(); + if (fileName.endsWith(".o") || fileName.endsWith(".h")) { + Path target = outputDirectory.resolve(fileName).toAbsolutePath(); + Files.copy(file, target, StandardCopyOption.REPLACE_EXISTING); + } + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + VMError.shouldNotReachHere("Fail to copy file from temporary", e); + } + } private void collectConfigs(Class<?> clazz, List<Method> methods) { reflectionCandidateTypes.putIfAbsent(clazz, false); diff --git a/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveMuslLibcFeature.java b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveMuslLibcFeature.java new file mode 100644 index 0000000..313ce5f --- /dev/null +++ b/sdk/enclave/src/main/java/com/alibaba/confidentialcomputing/enclave/system/EnclaveMuslLibcFeature.java @@ -0,0 +1,35 @@ +package com.alibaba.confidentialcomputing.enclave.system; + +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.c.libc.LibCBase; +import com.oracle.svm.core.posix.linux.libc.LibCFeature; +import com.oracle.svm.core.posix.linux.libc.MuslLibC; +import com.oracle.svm.core.util.UserError; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import org.graalvm.nativeimage.ImageSingletons; + +import java.util.ServiceLoader; + +@AutomaticFeature +public class EnclaveMuslLibcFeature extends LibCFeature { + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + String targetLibC = LibCOptions.UseLibC.getValue(); + ServiceLoader<LibCBase> loader = ServiceLoader.load(LibCBase.class); + for (LibCBase libc : loader) { + if (libc.getName().equals(targetLibC)) { + if (libc.getName().equals(MuslLibC.NAME)) { + if (JavaVersionUtil.JAVA_SPEC < 11) { + throw UserError.abort("Musl can only be used with labsjdk 11+."); + } + } else { + libc.checkIfLibCSupported(); + } + ImageSingletons.add(LibCBase.class, libc); + return; + } + } + throw UserError.abort("Unknown libc %s selected. Please use one of the available libc implementations.", targetLibC); + } +} diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/AroundNativeTest.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/AroundNativeTest.java deleted file mode 100644 index ec28e4e..0000000 --- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/AroundNativeTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.alibaba.confidentialcomputing.enclave; - -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; - -/** - * This class holds 2 main classes that are executed before and after maven surefire test by <a href="https://www.mojohaus.org/exec-maven-plugin/">exec-maven-plugin</a>. - */ -public class AroundNativeTest { - public static final Path tmpTestNativeLibsDir = Paths.get("/tmp/javaenclavetest-native-libs"); - - /** - * Before test starts, create the temporary directory to hold the dynamic native libraries that will be created - * during test. But the directory must be created beforehand, so that the {@code export LD_LIBRARY_PATH} action - * taken by surefire plugin can take effect. - */ - public static class PreTest { - public static void main(String[] args) throws IOException { - if (Files.notExists(tmpTestNativeLibsDir)) { - Files.createDirectories(tmpTestNativeLibsDir); - } - } - } - - public static class PostTest { - public static void main(String[] args) throws IOException { - if (Files.exists(tmpTestNativeLibsDir)) { - Files.walkFileTree(tmpTestNativeLibsDir, new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return super.visitFile(file, attrs); - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return super.postVisitDirectory(dir, exc); - } - }); - } - } - } -} diff --git a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java index ed676da..a9519f6 100644 --- a/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java +++ b/sdk/enclave/src/test/java/com/alibaba/confidentialcomputing/enclave/NativeImageTest.java @@ -21,6 +21,9 @@ public abstract class NativeImageTest implements NativeImageTestable { private static final String SVM_OUT = "svm-out"; private static final String SVM_ENCLAVE_LIB = "svm_enclave_sdk"; + private static final boolean useStaticLink = true; + public static final String ENC_INVOKE_ENTRY_TEST_C = "enc_invoke_entry_test.c"; + static { if (!GRAALVM_HOME.toFile().exists()) { throw new RuntimeException("System environment variable GRAALVM_HOME is set to " + GRAALVM_HOME @@ -99,11 +102,7 @@ public abstract class NativeImageTest implements NativeImageTestable { svmCompile(); afterSVMCompile(); compileJNILibrary(); - Path so1 = workingDir.resolve("lib" + JNI_LIB_NAME + ".so"); - Path so2 = workingDir.resolve("lib" + SVM_ENCLAVE_LIB + ".so"); - copyFile(so1, AroundNativeTest.tmpTestNativeLibsDir.resolve(so1.getFileName()), null); - copyFile(so2, AroundNativeTest.tmpTestNativeLibsDir.resolve(so2.getFileName()), null); - System.loadLibrary(JNI_LIB_NAME); + System.load(workingDir.resolve("lib" + JNI_LIB_NAME + ".so").toAbsolutePath().toString()); } private void collectSVMCompileItems() { @@ -163,8 +162,11 @@ public abstract class NativeImageTest implements NativeImageTestable { }); command.add(sb.deleteCharAt(sb.length() - 1).toString()); command.add("--shared"); + if (useStaticLink) { + command.add("--libc=musl"); + } command.add("--no-fallback"); - command.add("-H:OutputRelocatableImage=."); + // command.add("-H:OutputRelocatableImage=."); command.add("-H:Path=" + SVM_OUT); command.add("-H:+AllowIncompleteClasspath"); command.add("-H:+ReportExceptionStackTraces"); @@ -185,15 +187,55 @@ public abstract class NativeImageTest implements NativeImageTestable { requiredFilePaths.add(svmOutputDir.resolve("lib" + SVM_ENCLAVE_LIB + ".h")); requiredFilePaths.add(svmOutputDir.resolve("graal_isolate.h")); requiredFilePaths.add(svmOutputDir.resolve("enc_environment.h")); - requiredFilePaths.add(svmOutputDir.resolve("lib" + SVM_ENCLAVE_LIB + ".so")); + if (useStaticLink) { + requiredFilePaths.add(svmOutputDir.resolve("lib" + SVM_ENCLAVE_LIB + ".o")); + } else { + requiredFilePaths.add(svmOutputDir.resolve("lib" + SVM_ENCLAVE_LIB + ".so")); + } requiredFilePaths.forEach(p -> copyFile(p, workingDir.resolve(p.getFileName()), null)); List<String> command = new ArrayList<>(); + if (useStaticLink) { + prepareStaticLinkingCommand(command); + } else { + prepareDynamicLinkingCommand(command); + } + executeNewProcess(command, workingDir); + } + + private void prepareStaticLinkingCommand(List<String> command) { + Path graalvmHome = GRAALVM_HOME.toAbsolutePath(); + command.add("gcc"); + command.add("-z"); + command.add("noexecstack"); + command.add("-fPIC"); + command.add("-I" + graalvmHome.resolve("include").toString()); + command.add("-I" + graalvmHome.resolve("include/linux").toString()); + command.add(ENC_INVOKE_ENTRY_TEST_C); + command.add("lib" + SVM_ENCLAVE_LIB + ".o"); + command.add("-I."); + command.add("-L."); + command.add(graalvmHome.resolve("lib/svm/clibraries/linux-amd64/liblibchelper.a").toString()); + command.add(graalvmHome.resolve("lib/svm/clibraries/linux-amd64/libjvm.a").toString()); + command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libnio.a").toString()); + command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libzip.a").toString()); + command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libnet.a").toString()); + command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libjava.a").toString()); + command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libsunec.a").toString()); + command.add(graalvmHome.resolve("lib/static/linux-amd64/musl/libfdlibm.a").toString()); + command.add("-std=c99"); + command.add("-lc"); + command.add("-shared"); + command.add("-o"); + command.add("lib" + JNI_LIB_NAME + ".so"); + } + + private void prepareDynamicLinkingCommand(List<String> command) { command.add("gcc"); command.add("-fPIC"); command.add("-I" + GRAALVM_HOME.toAbsolutePath() + "/include"); command.add("-I" + GRAALVM_HOME.toAbsolutePath() + "/include/linux"); - command.add("enc_invoke_entry_test.c"); + command.add(ENC_INVOKE_ENTRY_TEST_C); command.add("-I."); command.add("-L."); command.add("-std=c99"); @@ -202,7 +244,6 @@ public abstract class NativeImageTest implements NativeImageTestable { command.add("-shared"); command.add("-o"); command.add("lib" + JNI_LIB_NAME + ".so"); - executeNewProcess(command, workingDir); } public static int executeNewProcess(List<String> command, Path workDir) { --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
