You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by sh...@apache.org on 2022/11/11 05:17:54 UTC

[incubator-teaclave-java-tee-sdk] 14/48: [Enc] Support static linking with musl

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 <ce...@alibaba-inc.com>
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: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org