yomaytk / elfconv

An experimental AOT compiler that translates Linux ELF binary to WebAssembly
Apache License 2.0
148 stars 6 forks source link

elfconv

elfconv is an experimental AOT compiler that translates a Linux ELF binary to executable WebAssembly. elfconv converts an original ELF binary to the LLVM bitcode using remill (library for lifting machine code to LLVM bitcode) and elfconv uses emscripten (for browser) or wasi-sdk (for WASI runtimes) to generate the WASM binary from the LLVM bitcode file.

Status

[!WARNING] "elfconv is a work in progress" and the test is insufficient, so you may fail to compile your ELF binary or execute the generated WASM binary. Current limitations are as follows.

  • Only support of aarch64 ELF binary as an input binary
  • Furthermore, a part of aarch64 instructions are not supported. If your ELF binary's instruction is not supported, elfconv outputs the message ([WARNING] Unsupported instruction at 0x...)
  • No support for stripped binaries
  • No support for shared objects
  • a lot of Linux system calls are unimplemented (ref: runtime/syscalls/)

    Quick Start

    You can try elfconv using the docker container (amd64 and arm64) by executing the commands as follows and can execute the WASM application on the both browser and host environment (WASI runtimes). [!WARNING] The container generated by the Dockerfile includes the installation of wasi-sdk. However, wasi-sdk doesn't release the package for arm64, so we build wasi-sdk in the arm64 container image, and it takes a long time. If you try elfconv, it might be good to use elfconv release packages, or comment out the lines of the installation of wasi-sdk (The relevant part is as follows in the Dockerfile) and try to execute only in the browser.

    elif [ "$( uname -m )" = "aarch64" ]; then \
    cd /root && git clone --recursive https://github.com/WebAssembly/wasi-sdk.git; \
    cd wasi-sdk && NINJA_FLAGS=-v make package; \
    fi

    Browser

    $ git clone --recursive https://github.com/yomaytk/elfconv
    $ cd elfconv
    elfconv/$ docker build . -t elfconv-image
    elfconv/$ docker run -it --rm -p 8080:8080 --name elfconv-container elfconv-image
    ### ENTRYPOINT: elfconv/scripts/container-entry-point.sh
    ### running build and test ...
    # You can test elfconv using `bin/elfconv.sh`
    ~/elfconv# cd bin
    ~/elfconv/bin# TARGET=browser ./elfconv.sh /path/to/ELF # e.g. ../examples/eratosthenes_sieve/a.out
    ~/elfconv/bin# emrun --no_browser --port 8080 exe.wasm.html
    Web server root directory: /root/elfconv/bin
    Now listening at http://0.0.0.0:8080/

    Now, the WASM application server has started, so that you can access it (e.g. http://localhost:8080/exe.wasm.html) from outside the container.

    Host (WASI runtimes)

    $ git clone --recursive https://github.com/yomaytk/elfconv
    $ cd elfconv
    $ docker build . -t elfconv-image
    $ docker run -it --name elfconv-container elfconv-image
    ### ENTRYPOINT: elfconv/scripts/container-entry-point.sh
    ### running build and test ...
    # You can test elfconv using `bin/elfconv.sh`
    ~/elfconv# cd bin
    ~/elfconv/bin# TARGET=wasi ./elfconv.sh /path/to/ELF # e.g. ../examples/eratosthenes_sieve/a.out
    ~/elfconv/bin# wasmedge exe.wasm # wasmedge is preinstalled

    Source code build

    1. Dev Container

    elfconv provides the Dev Container environment using the root Dockerfile and .devcontainer.json, so you can develop without making the build environment if you can use Dev Container on your vscode (Please refer to the official website of vscode for basically using Dev Container).

    2. Local Environment

    Dependencies

    The libraries required for the build are almost the same as those for remill, and the main libraries are as follows. The other required libraries are automatically installed using cxx-common.

Name Version
Git Latest
CMake 3.14+
Google Flags Latest
Google Log Latest
Google Test Latest
LLVM 16
Clang 16+
Intel XED Latest
Unzip Latest
ccache Latest

Build

If you prepare these libraries, you can easily build elfconv by executing scripts/build.sh as follows.

$ git clone --recursive https://github.com/yomaytk/elfconv
$ cd elfconv
/elfconv$ ./scripts/build.sh

[!NOTE] If you fail to build elfconv, please feel free to submit an issue!

Develop

After finishing the build, you can find the directory elfconv/build/, and you can build the 'lifter' ('lifter' is the module that converts the ELF binary to LLVM bitcode and those source codes are mainly located in the backend/remill/ and lifter/) by ninja after modifying the 'lifter' codes.

You can compile the ELF binary to the WASM binary using scripts/dev.sh as follows. dev.sh execute the translation (ELF -> LLVM bitcode by 'lifter') and compiles the runtime/ (statically linked with generated LLVM bitcode) and generate the WASM binary. when you execute the script, you should explicitly specify the path of the elfconv directory (/root/elfconv on the container) with NEW_ROOT or rewrite the ROOT_DIR in dev.sh.

### Browser
~/elfconv/build# NEW_ROOT=/path/to/elfconv TARGET=browser ../scripts/dev.sh path/to/ELF # generate the WASM binary under the elfconv/build/lifter
~/elfconv/build# emrun --no_browser --port 8080 ./lifter/exe.wasm.html # execute the generated WASM binary with emscripten
------------------------
### Host (WASI Runtimes)
~/elfconv/build# NEW_ROOT=/path/to/elfconv TARGET=wasi ../scripts/dev.sh path/to/ELF
~/elfconv/build# wasmedge ./lifter/exe.wasm

Acknowledgement

elfconv uses or references some projects as follows. Great thanks to its all developers!