From c55f08670d8645eadf76578cd414d4769625294b Mon Sep 17 00:00:00 2001 From: yomaytk Date: Sat, 23 Nov 2024 07:33:57 +0000 Subject: [PATCH 1/4] Fix the scripts and add sample html script for Wasm on browser. --- .gitignore | 3 +- bin/elfconv.sh | 76 ++++++++++++++++++++++++------------------------- bin/exe.html | 29 +++++++++++++++++++ lifter/Lift.cpp | 3 +- scripts/dev.sh | 68 ++++++++++++++++++------------------------- 5 files changed, 97 insertions(+), 82 deletions(-) create mode 100644 bin/exe.html diff --git a/.gitignore b/.gitignore index 7814044..133c563 100644 --- a/.gitignore +++ b/.gitignore @@ -118,4 +118,5 @@ examples/tests SHA* elfconv-v* -!examples/browser/exe.html \ No newline at end of file +!examples/browser/exe.html +!bin/exe.html \ No newline at end of file diff --git a/bin/elfconv.sh b/bin/elfconv.sh index 234be57..db784a7 100755 --- a/bin/elfconv.sh +++ b/bin/elfconv.sh @@ -10,21 +10,16 @@ setting() { BUILD_LIFTER_DIR=${BUILD_DIR}/lifter EMCC=emcc EMAR=emar - OPTFLAGS="-O3" + OPTFLAGS="-O0" EMCCFLAGS="${OPTFLAGS} -I${ROOT_DIR}/backend/remill/include -I${ROOT_DIR}" ELFCONV_MACROS="-DELFC_BROWSER_ENV=1" - ELFCONV_DEBUG_MACROS= ELFPATH=$( realpath "$1" ) WASMCC=$EMCC WASMCCFLAGS=$EMCCFLAGS WASMAR=$EMAR WASISDKCXX=${WASI_SDK_PATH}/bin/clang++ WASISDKAR=${WASI_SDK_PATH}/bin/ar - WASISDKFLAGS="${OPTFLAGS} --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -I${ROOT_DIR}/backend/remill/include -I${ROOT_DIR} -fno-exceptions" - - if [ "$TARGET" = "wasm-host" ]; then - ELFCONV_MACROS="-DELFC_WASI_ENV=1" - fi + WASISDKFLAGS="${OPTFLAGS} --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -D_WASI_EMULATED_PROCESS_CLOCKS -I${ROOT_DIR}/backend/remill/include -I${ROOT_DIR} -fno-exceptions" } @@ -38,56 +33,61 @@ main() { exit 1 fi - # build runtime - SYSCALLCPP="syscalls/SyscallBrowser.cpp" - echo -e "[\033[32mINFO\033[0m] Building elfconv-Runtime ..." - if [ "$TARGET" = "wasm-host" ]; then + # setting for WASI + wasi32_target_arch='' + if [ "$TARGET" = "Wasi" ]; then WASMCC=$WASISDKCXX WASMCCFLAGS=$WASISDKFLAGS WASMAR=$WASISDKAR - SYSCALLCPP="syscalls/SyscallWasi.cpp" + ELFCONV_MACROS="-DELFC_WASI_ENV=1" + wasi32_target_arch='wasi32' fi - cd "${RUNTIME_DIR}" || { echo "cd Failure"; exit 1; } - # shellcheck disable=SC2086 - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Entry.o -c Entry.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Runtime.o -c Runtime.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Memory.o -c Memory.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Syscall.o -c $SYSCALLCPP && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o VmIntrinsics.o -c VmIntrinsics.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Util.o -c "${UTILS_DIR}"/Util.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o elfconv.o -c "${UTILS_DIR}"/elfconv.cpp && \ - $WASMAR rcs libelfconv.a Entry.o Runtime.o Memory.o Syscall.o VmIntrinsics.o Util.o elfconv.o - mv libelfconv.a "${BIN_DIR}/" - rm *.o - echo -e "[\033[32mINFO\033[0m] Generate libelfconv.a." - # ELF -> LLVM bc + # build runtime + echo -e "[\033[32mINFO\033[0m] Building elfconv-Runtime ..." + # build runtime/*.cpp + for cpp_file in ${RUNTIME_DIR}/*.cpp; do + $WASMCC $WASMCCFLAGS $ELFCONV_MACROS -c "$cpp_file" -o "${cpp_file%.cpp}".wasm.o + done + # build utils/*.cpp + for cpp_file in ${UTILS_DIR}/*.cpp; do + $WASMCC $WASMCCFLAGS $ELFCONV_MACROS -c "$cpp_file" -o "${cpp_file%.cpp}".wasm.o + done + # build runtime/syscalls/Syscall${TARGET}.cpp + $WASMCC $WASMCCFLAGS $ELFCONV_MACROS -c "${RUNTIME_DIR}/syscalls/Syscall${TARGET}.cpp" -o "Syscall${TARGET}.wasm.o" + $WASMAR rcs libelfconv.a *.wasm.o + mv libelfconv.a "${BIN_DIR}/" + rm *.wasm.o + echo -e "[\033[32mINFO\033[0m] libelfconv.a was generated." + + # ELF -> LLVM bitcode cp -p "${BUILD_LIFTER_DIR}/elflift" "${BIN_DIR}/" - echo -e "[\033[32mINFO\033[0m] Converting ELF to LLVM bitcode ..." + echo -e "[\033[32mINFO\033[0m] ELF -> LLVM bitcode..." cd "${BIN_DIR}" || { echo "cd Failure"; exit 1; } ./elflift \ --arch aarch64 \ --bc_out lift.bc \ --target_elf "$ELFPATH" \ - --dbg_fun_cfg "$2" + --dbg_fun_cfg "$2" \ + --target_arch "$wasm32_target_arch" echo -e "[\033[32mINFO\033[0m] Generate lift.bc." # LLVM bc -> target file case "$TARGET" in - browser) - echo -e "[\033[32mINFO\033[0m] Converting LLVM bitcode to WASM binary (for browser) ..." + Browser) + # We use https://github.com/mame/xterm-pty for the console on the browser. + echo -e "[\033[32mINFO\033[0m] Compiling to Wasm and Js (for Browser)... " cd "${BIN_DIR}" || { echo "cd Failure"; exit 1; } - $WASMCC -c lift.bc -o lift.o && \ - $WASMCC -o exe.wasm.html -L"./" -sWASM -sALLOW_MEMORY_GROWTH lift.o -lelfconv - echo -e "[\033[32mINFO\033[0m] Generate WASM binary." + $WASMCC $OPTFLAGS -sALLOW_MEMORY_GROWTH -sASYNCIFY -sEXPORT_ES6 -sENVIRONMENT=web --js-library ${ROOT_DIR}/xterm-pty/emscripten-pty.js \ + -o exe.js -L"./" lift.bc -lelfconv + echo -e "[\033[32mINFO\033[0m] exe.wasm and exe.js were generated." return 0 ;; - wasi) - echo -e "[\033[32mINFO\033[0m] Converting LLVM bitcode to WASM binary (for server) ..." + Wasi) + echo -e "[\033[32mINFO\033[0m] Compiling to Wasm (for WASI)... " cd "${BIN_DIR}" || { echo "cd Failure"; exit 1; } - $WASMCC -c lift.bc -o lift.o && \ - $WASMCC -o exe.wasm -L"./" lift.o -lelfconv - echo -e "[\033[32mINFO\033[0m] Generate WASM binary." + $WASMCC $OPTFLAGS -o exe.wasm -L"./" lift.bc -lelfconv + echo -e "[\033[32mINFO\033[0m] exe.wasm was generated." return 0 ;; esac diff --git a/bin/exe.html b/bin/exe.html new file mode 100644 index 0000000..8a076df --- /dev/null +++ b/bin/exe.html @@ -0,0 +1,29 @@ + + + + + + + + +
+ + + \ No newline at end of file diff --git a/lifter/Lift.cpp b/lifter/Lift.cpp index 56b58d2..200a650 100644 --- a/lifter/Lift.cpp +++ b/lifter/Lift.cpp @@ -134,7 +134,7 @@ int main(int argc, char *argv[]) { host_arch->PrepareModule(module.get()); // Set wasm32-unknown-wasi and wasm32 data layout if necessary. - if (FLAGS_target_arch == "wasm32") { + if (FLAGS_target_arch == "wasi32") { auto wasm32_dl = llvm::DataLayout("e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20"); module->setDataLayout(wasm32_dl.getStringRepresentation()); @@ -147,6 +147,5 @@ int main(int argc, char *argv[]) { remill::StoreModuleToFile(module.get(), FLAGS_bc_out); - printf("[\033[32mINFO\033[0m] Lift Done.\n"); return 0; } diff --git a/scripts/dev.sh b/scripts/dev.sh index 77e2dd2..da52ac7 100755 --- a/scripts/dev.sh +++ b/scripts/dev.sh @@ -27,6 +27,8 @@ setting() { ELFCONV_DEBUG_MACROS= WASMCC=$EMCC WASMCCFLAGS=$EMCCFLAGS + WASMEDGE_COMPILE_OPT="wasmedge compile --optimize 3" + HOST_CPU=$(uname -p) if [ -n "$DEBUG" ]; then ELFCONV_DEBUG_MACROS="-DELFC_RUNTIME_SYSCALL_DEBUG=1 -DELFC_RUNTIME_MULSECTIONS_WARNING=1 " @@ -56,12 +58,12 @@ aarch64_test() { lifting() { # ELF -> LLVM bc - echo -e "[\033[32mINFO\033[0m] ELF Converting Start." + echo -e "[\033[32mINFO\033[0m] ELF -> LLVM bitcode..." elf_path=$( realpath "$1" ) - wasm32_target_arch='' - if [ "${TARGET}" == "wasi" ]; then - wasm32_target_arch='wasm32' + wasi32_target_arch='' + if [ "${TARGET}" == "Wasi" ]; then + wasi32_target_arch='wasi32' fi cd ${BUILD_LIFTER_DIR} && \ @@ -71,9 +73,9 @@ lifting() { --target_elf "$elf_path" \ --dbg_fun_cfg "$2" \ --bitcode_path "$3" \ - --target_arch "$wasm32_target_arch" && \ + --target_arch "$wasi32_target_arch" && \ llvm-dis-${LLVM_VERSION} lift.bc -o lift.ll - echo -e "[\033[32mINFO\033[0m] Generate lift.bc." + echo -e "[\033[32mINFO\033[0m] lift.bc was generated." } @@ -95,54 +97,38 @@ main() { # LLVM bc -> target file case "${TARGET}" in - native) - cd ${BUILD_LIFTER_DIR} && \ - ${CXX} ${CLANGFLAGS} -o exe.aarch64 lift.ll ${RUNTIME_DIR}/Entry.cpp ${RUNTIME_DIR}/Runtime.cpp ${RUNTIME_DIR}/Memory.cpp ${RUNTIME_DIR}/syscalls/SyscallNative.cpp ${RUNTIME_DIR}/VmIntrinsics.cpp ${UTILS_DIR}/Util.cpp ${UTILS_DIR}/elfconv.cpp - echo -e "[\033[32mINFO\033[0m] Generate native binary." + Native) + echo -e "[\033[32mINFO\033[0m] Compiling to Native binary (for $HOST_CPU)... " + ${CXX} ${CLANGFLAGS} -o "exe.${HOST_CPU}" lift.ll ${RUNTIME_DIR}/Entry.cpp ${RUNTIME_DIR}/Runtime.cpp ${RUNTIME_DIR}/Memory.cpp ${RUNTIME_DIR}/syscalls/SyscallNative.cpp ${RUNTIME_DIR}/VmIntrinsics.cpp ${UTILS_DIR}/Util.cpp ${UTILS_DIR}/elfconv.cpp + echo -e " [\033[32mINFO\033[0m] exe.${HOST_CPU} was generated." return 0 ;; - browser) + Browser) ELFCONV_MACROS="-DELFC_BROWSER_ENV=1" - cd "${BUILD_LIFTER_DIR}" && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Entry.wasm.o -c ${RUNTIME_DIR}/Entry.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Runtime.wasm.o -c ${RUNTIME_DIR}/Runtime.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Memory.wasm.o -c ${RUNTIME_DIR}/Memory.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Syscall.wasm.o -c ${RUNTIME_DIR}/syscalls/SyscallBrowser.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o VmIntrinsics.wasm.o -c ${RUNTIME_DIR}/VmIntrinsics.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Util.wasm.o -c ${UTILS_DIR}/Util.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o elfconv.wasm.o -c ${UTILS_DIR}/elfconv.cpp && \ - $WASMCC $WASMCCFLAGS -c lift.ll -o lift.wasm.o - $WASMCC $WASMCCFLAGS -o exe.js -sALLOW_MEMORY_GROWTH -sASYNCIFY -sEXPORT_ES6 -sENVIRONMENT=web --js-library ${ROOT_DIR}/xterm-pty/emscripten-pty.js \ - lift.wasm.o Entry.wasm.o Runtime.wasm.o Memory.wasm.o Syscall.wasm.o \ - VmIntrinsics.wasm.o Util.wasm.o elfconv.wasm.o - echo -e "[\033[32mINFO\033[0m] Generate WASM binary." + echo -e "[\033[32mINFO\033[0m] Compiling to Wasm and Js (for Browser)... " + $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o exe.js -sALLOW_MEMORY_GROWTH -sASYNCIFY -sEXPORT_ES6 -sENVIRONMENT=web --js-library ${ROOT_DIR}/xterm-pty/emscripten-pty.js \ + lift.ll ${RUNTIME_DIR}/Entry.cpp ${RUNTIME_DIR}/Runtime.cpp ${RUNTIME_DIR}/Memory.cpp ${RUNTIME_DIR}/syscalls/SyscallBrowser.cpp \ + ${RUNTIME_DIR}/VmIntrinsics.cpp ${UTILS_DIR}/Util.cpp ${UTILS_DIR}/elfconv.cpp + echo -e "[\033[32mINFO\033[0m] exe.wasm and exe.js were generated." cp exe.js ${ROOT_DIR}/examples/browser cp exe.wasm ${ROOT_DIR}/examples/browser - # delete obj - cd "${BUILD_LIFTER_DIR}" && rm *.o return 0 ;; - wasi) + Wasi) ELFCONV_MACROS="-DELFC_WASI_ENV=1" WASMCC=$WASISDK_CXX WASMCCFLAGS=$WASISDKFLAGS ELFCONV_MACROS="${ELFCONV_MACROS} -fno-exceptions" - cd "${BUILD_LIFTER_DIR}" && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Entry.wasm.o -c ${RUNTIME_DIR}/Entry.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Runtime.wasm.o -c ${RUNTIME_DIR}/Runtime.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Memory.wasm.o -c ${RUNTIME_DIR}/Memory.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Syscall.wasm.o -c ${RUNTIME_DIR}/syscalls/SyscallWasi.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o VmIntrinsics.wasm.o -c ${RUNTIME_DIR}/VmIntrinsics.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o Util.wasm.o -c ${UTILS_DIR}/Util.cpp && \ - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o elfconv.wasm.o -c ${UTILS_DIR}/elfconv.cpp && \ - $WASMCC -O3 -c lift.ll -o lift.wasm.o - $WASMCC -O3 $WASISDK_LINKFLAGS -o exe.wasm lift.wasm.o Entry.wasm.o Runtime.wasm.o Memory.wasm.o Syscall.wasm.o VmIntrinsics.wasm.o Util.wasm.o elfconv.wasm.o - echo -e "[\033[32mINFO\033[0m] Generate WASM binary." - # delete obj - cd "${BUILD_LIFTER_DIR}" && rm *.o + cd ${BUILD_DIR} + echo -e "[\033[32mINFO\033[0m] Compiling to Wasm (for WASI)... " + $WASMCC -O3 $WASMCCFLAGS $WASISDK_LINKFLAGS $ELFCONV_MACROS $ELFCONV_DEBUG_MACROS -o exe.wasm ${BUILD_LIFTER_DIR}/lift.ll ${RUNTIME_DIR}/Entry.cpp ${RUNTIME_DIR}/Runtime.cpp ${RUNTIME_DIR}/Memory.cpp \ + ${RUNTIME_DIR}/syscalls/SyscallWasi.cpp ${RUNTIME_DIR}/VmIntrinsics.cpp ${UTILS_DIR}/Util.cpp ${UTILS_DIR}/elfconv.cpp + echo -e "[\033[32mINFO\033[0m] exe.wasm was generated." + $WASMEDGE_COMPILE_OPT exe.wasm exe_o3.wasm + echo -e "[\033[32mINFO\033[0m] Universal compile optimization was done. (exe_ao3.wasm)" return 0 ;; esac } -main "$@" +main "$@" \ No newline at end of file From bab290c32e464ada816ea491dd7eb6ae3a955c04 Mon Sep 17 00:00:00 2001 From: yomaytk Date: Sat, 23 Nov 2024 08:26:01 +0000 Subject: [PATCH 2/4] Fix some bugs. --- bin/elfconv.sh | 52 ++++++++++++++++---------------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/bin/elfconv.sh b/bin/elfconv.sh index db784a7..bd876e6 100755 --- a/bin/elfconv.sh +++ b/bin/elfconv.sh @@ -8,18 +8,14 @@ setting() { UTILS_DIR=${ROOT_DIR}/utils BUILD_DIR=${ROOT_DIR}/build BUILD_LIFTER_DIR=${BUILD_DIR}/lifter - EMCC=emcc - EMAR=emar OPTFLAGS="-O0" + EMCC=emcc EMCCFLAGS="${OPTFLAGS} -I${ROOT_DIR}/backend/remill/include -I${ROOT_DIR}" + WASISDKCC=${WASI_SDK_PATH}/bin/clang++ + WASISDKFLAGS="${OPTFLAGS} --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -D_WASI_EMULATED_PROCESS_CLOCKS -I${ROOT_DIR}/backend/remill/include -I${ROOT_DIR} -fno-exceptions" + WASISDK_LINKFLAGS="-lwasi-emulated-process-clocks" ELFCONV_MACROS="-DELFC_BROWSER_ENV=1" ELFPATH=$( realpath "$1" ) - WASMCC=$EMCC - WASMCCFLAGS=$EMCCFLAGS - WASMAR=$EMAR - WASISDKCXX=${WASI_SDK_PATH}/bin/clang++ - WASISDKAR=${WASI_SDK_PATH}/bin/ar - WASISDKFLAGS="${OPTFLAGS} --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -D_WASI_EMULATED_PROCESS_CLOCKS -I${ROOT_DIR}/backend/remill/include -I${ROOT_DIR} -fno-exceptions" } @@ -36,30 +32,9 @@ main() { # setting for WASI wasi32_target_arch='' if [ "$TARGET" = "Wasi" ]; then - WASMCC=$WASISDKCXX - WASMCCFLAGS=$WASISDKFLAGS - WASMAR=$WASISDKAR - ELFCONV_MACROS="-DELFC_WASI_ENV=1" wasi32_target_arch='wasi32' fi - # build runtime - echo -e "[\033[32mINFO\033[0m] Building elfconv-Runtime ..." - # build runtime/*.cpp - for cpp_file in ${RUNTIME_DIR}/*.cpp; do - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS -c "$cpp_file" -o "${cpp_file%.cpp}".wasm.o - done - # build utils/*.cpp - for cpp_file in ${UTILS_DIR}/*.cpp; do - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS -c "$cpp_file" -o "${cpp_file%.cpp}".wasm.o - done - # build runtime/syscalls/Syscall${TARGET}.cpp - $WASMCC $WASMCCFLAGS $ELFCONV_MACROS -c "${RUNTIME_DIR}/syscalls/Syscall${TARGET}.cpp" -o "Syscall${TARGET}.wasm.o" - $WASMAR rcs libelfconv.a *.wasm.o - mv libelfconv.a "${BIN_DIR}/" - rm *.wasm.o - echo -e "[\033[32mINFO\033[0m] libelfconv.a was generated." - # ELF -> LLVM bitcode cp -p "${BUILD_LIFTER_DIR}/elflift" "${BIN_DIR}/" echo -e "[\033[32mINFO\033[0m] ELF -> LLVM bitcode..." @@ -69,29 +44,34 @@ main() { --bc_out lift.bc \ --target_elf "$ELFPATH" \ --dbg_fun_cfg "$2" \ - --target_arch "$wasm32_target_arch" - echo -e "[\033[32mINFO\033[0m] Generate lift.bc." + --target_arch "$wasi32_target_arch" + echo -e "[\033[32mINFO\033[0m] LLVM bitcode (lift.bc) was generated." # LLVM bc -> target file case "$TARGET" in Browser) # We use https://github.com/mame/xterm-pty for the console on the browser. + ELFCONV_MACROS="-DELFC_BROWSER_ENV=1" echo -e "[\033[32mINFO\033[0m] Compiling to Wasm and Js (for Browser)... " cd "${BIN_DIR}" || { echo "cd Failure"; exit 1; } - $WASMCC $OPTFLAGS -sALLOW_MEMORY_GROWTH -sASYNCIFY -sEXPORT_ES6 -sENVIRONMENT=web --js-library ${ROOT_DIR}/xterm-pty/emscripten-pty.js \ - -o exe.js -L"./" lift.bc -lelfconv + $EMCC $EMCCFLAGS $ELFCONV_MACROS -sALLOW_MEMORY_GROWTH -sASYNCIFY -sEXPORT_ES6 -sENVIRONMENT=web --js-library ${ROOT_DIR}/xterm-pty/emscripten-pty.js \ + -o exe.js lift.bc ${RUNTIME_DIR}/Entry.cpp ${RUNTIME_DIR}/Memory.cpp ${RUNTIME_DIR}/Runtime.cpp ${RUNTIME_DIR}/VmIntrinsics.cpp ${RUNTIME_DIR}/syscalls/SyscallBrowser.cpp \ + ${UTILS_DIR}/elfconv.cpp ${UTILS_DIR}/Util.cpp echo -e "[\033[32mINFO\033[0m] exe.wasm and exe.js were generated." - return 0 ;; Wasi) echo -e "[\033[32mINFO\033[0m] Compiling to Wasm (for WASI)... " + ELFCONV_MACROS="-DELFC_WASI_ENV=1" cd "${BIN_DIR}" || { echo "cd Failure"; exit 1; } - $WASMCC $OPTFLAGS -o exe.wasm -L"./" lift.bc -lelfconv + $WASISDKCC $WASISDKFLAGS $WASISDK_LINKFLAGS $ELFCONV_MACROS -o exe.wasm lift.bc ${RUNTIME_DIR}/Entry.cpp ${RUNTIME_DIR}/Memory.cpp ${RUNTIME_DIR}/Runtime.cpp ${RUNTIME_DIR}/VmIntrinsics.cpp ${RUNTIME_DIR}/syscalls/SyscallWasi.cpp \ + ${UTILS_DIR}/elfconv.cpp ${UTILS_DIR}/Util.cpp echo -e "[\033[32mINFO\033[0m] exe.wasm was generated." - return 0 ;; esac + rm ${BIN_DIR}/lift.bc + return 0 + } main "$@" \ No newline at end of file From 6a5623f09230f8f52b064784cfe63d8f38a48135 Mon Sep 17 00:00:00 2001 From: yomaytk Date: Sat, 23 Nov 2024 08:30:15 +0000 Subject: [PATCH 3/4] Minor fix. --- backend/remill/lib/BC/TraceLifter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/remill/lib/BC/TraceLifter.cpp b/backend/remill/lib/BC/TraceLifter.cpp index d1920d4..30051ae 100644 --- a/backend/remill/lib/BC/TraceLifter.cpp +++ b/backend/remill/lib/BC/TraceLifter.cpp @@ -969,7 +969,7 @@ void TraceLifter::Impl::Optimize() { int opt_cnt = 1; for (auto lifted_func : no_indirect_lifted_funcs) { std::cout << "\r[" - << "\033[1;32m" + << "\033[32m" << "INFO" << "\033[0m" << "]" @@ -1001,7 +1001,7 @@ void TraceLifter::Impl::Optimize() { int opt_cnt2 = 1; for (auto lifted_func : no_indirect_lifted_funcs) { std::cout << "\r[" - << "\033[1;32m" + << "\033[32m" << "INFO" << "\033[0m" << "]" From 8bd42b9e16d38d93f36adcc87a0e345257ed0454 Mon Sep 17 00:00:00 2001 From: yomaytk Date: Sat, 23 Nov 2024 09:32:46 +0000 Subject: [PATCH 4/4] Fix some scripts for Quick Start. --- Dockerfile | 5 +++-- README.md | 27 ++++++++++++++------------- bin/elfconv.sh | 2 +- scripts/dev.sh | 2 +- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index b65ca84..327c2cb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -49,8 +49,9 @@ git pull && ./emsdk install latest && ./emsdk activate latest && . ./emsdk_env.s # takes long times to build wasi-sdk in arm64 because wasi-sdk doesn't release arm64 packages. RUN \ if [ "$( uname -m )" = "x86_64" ]; then \ - cd /root && export WASI_VERSION=21 && export WASI_VERSION_FULL=${WASI_VERSION}.0 && ( echo "export WASI_VERSION=21"; echo "export WASI_VERSION_FULL=${WASI_VERSION}.0"; echo "export WASI_SDK_PATH=/root/wasi-sdk-${WASI_VERSION_FULL}" ) >> /root/.bash_profile && \ - wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz && tar xvf wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz && rm wasi-sdk-${WASI_VERSION_FULL}-linux.tar.gz; \ + cd /root && export WASI_OS=linux && export WASI_ARCH=x86_64 && export WASI_VERSION=24 && export WASI_VERSION_FULL=${WASI_VERSION}.0 && \ + ( echo "export WASI_OS=linux"; echo "export WASI_ARCH=x86_64"; echo "export WASI_VERSION=24"; echo "export WASI_VERSION_FULL=${WASI_VERSION}.0"; echo "export WASI_SDK_PATH=/root/wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}" ) >> /root/.bash_profile && \ + wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_VERSION}/wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}.tar.gz && tar xvf wasi-sdk-${WASI_VERSION_FULL}-${WASI_ARCH}-${WASI_OS}.tar.gz; \ elif [ "$( uname -m )" = "aarch64" ]; then \ cd /root && echo "export WASI_SDK_PATH=/root/wasi-sdk/build/install/opt/wasi-sdk" >> /root/.bash_profile && git clone --recursive https://github.com/WebAssembly/wasi-sdk.git; \ cd wasi-sdk && NINJA_FLAGS=-v make package; \ diff --git a/README.md b/README.md index ca98487..10a0418 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ elfconv converts an original ELF binary to the LLVM bitcode using [remill](https and elfconv uses [emscripten](https://github.com/emscripten-core/emscripten) (for browser) or [wasi-sdk](https://github.com/WebAssembly/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. +"**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 @@ -13,7 +12,6 @@ and elfconv uses [emscripten](https://github.com/emscripten-core/emscripten) (fo - a lot of Linux system calls are unimplemented (ref: [`runtime/syscalls/`](https://github.com/yomaytk/elfconv/blob/main/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](https://github.com/WebAssembly/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](https://github.com/yomaytk/elfconv/releases), 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. > ```bash > elif [ "$( uname -m )" = "aarch64" ]; then \ @@ -25,13 +23,13 @@ You can try elfconv using the docker container (amd64 and arm64) by executing th ```bash $ 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 +elfconv/$ docker build . -t +elfconv/$ docker run -it --rm -p 8080:8080 --name ### 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# TARGET=Browser ./elfconv.sh /path/to/ELF # e.g. ../examples/hello/a.out +# exe.js and exe.wasm should be generated. ~/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/ @@ -41,13 +39,12 @@ Now, the WASM application server has started, so that you can access it (e.g. ht ```bash $ 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 +$ docker build . -t +$ docker run -it --name ### 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# TARGET=Wasi ./elfconv.sh /path/to/ELF # e.g. ../examples/hello/a.out ~/elfconv/bin# wasmtime exe.wasm # wasmtime is preinstalled ``` ## Source code build @@ -84,12 +81,16 @@ After finishing the build, you can find the directory `elfconv/build/`, and you You can compile the ELF binary to the WASM binary using [`scripts/dev.sh`](https://github.com/yomaytk/elfconv/blob/main/scripts/dev.sh) as follows. `dev.sh` execute the translation (ELF -> LLVM bitcode by *'lifter'*) and compiles the [`runtime/`](https://github.com/yomaytk/elfconv/tree/main/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`. ```bash +### Native +~/elfconv/build# NEW_ROOT=/path/to/elfconv TARGET=Native ../scripts/dev.sh path/to/ELF # generate the Native binary (Host achitecture) under the elfconv/build/lifter +~/elfconv/build# ./exe.${HOST_CPU} +------------------------ ### 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# 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# NEW_ROOT=/path/to/elfconv TARGET=Wasi ../scripts/dev.sh path/to/ELF ~/elfconv/build# wasmedge ./lifter/exe.wasm ``` ## Acknowledgement diff --git a/bin/elfconv.sh b/bin/elfconv.sh index bd876e6..9959d60 100755 --- a/bin/elfconv.sh +++ b/bin/elfconv.sh @@ -8,7 +8,7 @@ setting() { UTILS_DIR=${ROOT_DIR}/utils BUILD_DIR=${ROOT_DIR}/build BUILD_LIFTER_DIR=${BUILD_DIR}/lifter - OPTFLAGS="-O0" + OPTFLAGS="-O3" EMCC=emcc EMCCFLAGS="${OPTFLAGS} -I${ROOT_DIR}/backend/remill/include -I${ROOT_DIR}" WASISDKCC=${WASI_SDK_PATH}/bin/clang++ diff --git a/scripts/dev.sh b/scripts/dev.sh index da52ac7..961a834 100755 --- a/scripts/dev.sh +++ b/scripts/dev.sh @@ -125,7 +125,7 @@ main() { ${RUNTIME_DIR}/syscalls/SyscallWasi.cpp ${RUNTIME_DIR}/VmIntrinsics.cpp ${UTILS_DIR}/Util.cpp ${UTILS_DIR}/elfconv.cpp echo -e "[\033[32mINFO\033[0m] exe.wasm was generated." $WASMEDGE_COMPILE_OPT exe.wasm exe_o3.wasm - echo -e "[\033[32mINFO\033[0m] Universal compile optimization was done. (exe_ao3.wasm)" + echo -e "[\033[32mINFO\033[0m] Universal compile optimization was done. (exe_o3.wasm)" return 0 ;; esac