Skip to content

Files

Latest commit

95df90d · Aug 23, 2024

History

History

ffm-objfile-runner

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Aug 23, 2024
Aug 23, 2024
Aug 23, 2024

概要

GCC の -c で得られるオブジェクトファイルを Foreign Function & Memory API を使って実行します。

Warning

動的リンカが働かないため、 printf() など libc を含む外部ライブラリの呼び出しは機能しません。

必要なもの

  • Java 22
  • Maven
  • GCC

使い方

$ mvn package
$ mvn exec:exec@run

呼び出し対象の C ソースは src/main/native/test.c です。呼び出す関数は pom.xml の以下の部分で変更可能です。

<execution>
    <id>run</id>
    <phase>exec</phase>
    <goals>
        <goal>exec</goal>
    </goals>
    <configuration>
        <executable>${java.home}/bin/java</executable>
        <arguments>
            <argument>--enable-preview</argument>
            <argument>-jar</argument>
            <argument>${project.build.directory}/${imageName}.jar</argument>
            <argument>${project.build.directory}/test.o</argument>
            <!-- ここで関数を指定する(mul2 か mul3) -->
            <argument>mul2</argument>
            <!-- <argument>mul3</argument> -->
        </arguments>
    </configuration>
</execution>

カラクリ

gcc -c で得られたオブジェクトファイルを FileChannel::mapMappedByteBuffer にマップします。そこから MemorySegmentofBuffer() で取得します。

FileChannel::map には MemorySegment を返すものも存在しますが、ELF の解析に使う JElf v0.9.0 の ElfFileByteBuffer 系は MappedByteBuffer しか受け付けないため、これを経由して MemorySegment を取得するようにします。

これに FFM 経由で mprotect() で実行ビットを立て、実行可能メモリセグメントにします。ELF から取得した関数開始オフセットに対して MethodHandle を作成し、実行します。