Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,10 @@ examples/tests
# release
SHA*
elfconv-v*
release/outdir

!browser/*
!release/outdir/index.html
!release/outdir/elfconv.sh
!tests/browser/*.js
!tests/browser/*.html
!tests/browser/package.json
Expand Down
19 changes: 11 additions & 8 deletions release/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# How to use release packages
This shows how to use the release packages.
This shows how to use the release packages.

Release Page: https://github.com/yomaytk/elfconv/releases

## Quick Start
You can translate the ELF binary to the WASM binary using `outdir` directory.

### settings
You should prepare [Emscripten](https://github.com/emscripten-core/emscripten), [WASI-SDK](https://github.com/WebAssembly/wasi-sdk) and WASI runtimes (e.g., [WasmEdge](https://github.com/WasmEdge/WasmEdge), [wasmtime](https://github.com/bytecodealliance/wasmtime))
### command
After configuring the above settings, you can try translation by the command as follows.
### Prerequisites
- [Emscripten](https://github.com/emscripten-core/emscripten) (for browser target)
- [WASI-SDK](https://github.com/WebAssembly/wasi-sdk) (for WASI target)
- WASI runtimes (e.g., [WasmEdge](https://github.com/WasmEdge/WasmEdge), [wasmtime](https://github.com/bytecodealliance/wasmtime))

### Command
```bash
$ tar -zxvf elfconv-v0.2.0-linux-amd64.tar.gz
$ tar -zxvf elfconv-<VERSION>-linux-<arch>.tar.gz
$ cd outdir
$ TARGET=aarch64-wasm ./elfconv.sh </path/to/ELF> # generates out/exe.wasm
$ TARGET=aarch64-wasm INITWASM=1 ./elfconv.sh /path/to/elf
```

For more build options (WASI target, multi-process, directory mounting, etc.), see [scripts/README.md](https://github.com/yomaytk/elfconv/blob/main/scripts/README.md).
117 changes: 82 additions & 35 deletions release/outdir/elfconv.sh
Original file line number Diff line number Diff line change
@@ -1,37 +1,82 @@
#!/usr/bin/env bash

set -e

GREEN="\033[32m"
ORANGE="\033[33m"
RED="\033[31m"
NC="\033[0m"

setting() {

EMCC=emcc
EMCC=em++
WASISDKCXX=${WASI_SDK_PATH}/bin/clang++
ELFPATH=$( realpath "$1" )
ELFNAME=$( basename "$ELFPATH" )
RT_OP="-O3"
OUT="out"
PRELOAD=
BROWSER_DIR="./browser"
EMCC_OPTION="-sASYNCIFY=0 -sINITIAL_MEMORY=536870912 -sSTACK_SIZE=16MB -sPTHREAD_POOL_SIZE=0 -pthread -sALLOW_MEMORY_GROWTH -sEXPORT_ES6 -sENVIRONMENT=web,worker"
WASISDK_COMPILEFLAGS="--sysroot=${WASI_SDK_PATH}/share/wasi-sysroot -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_PROCESS_CLOCKS -D_WASI_EMULATED_MMAN -fno-exceptions"
WASISDK_LINKFLAGS="-lwasi-emulated-process-clocks -lwasi-emulated-mman -lwasi-emulated-signal"
WASMEDGE_COMPILE_OPT="wasmedge compile --optimize 3"

}

main() {
prepare_js() {

MAINGENJS="${OUT}/${ELFNAME}.generated.js"
MAINGENWASM="${OUT}/${ELFNAME}.generated.wasm"
OUTWASM="${OUT}/${ELFNAME}.wasm"
OUTJS="${OUT}/${ELFNAME}.js"
OUTHTML="${OUT}/main.html"

cp -p "${BROWSER_DIR}/process.js" "${OUT}"
cp -p "${BROWSER_DIR}/coi-serviceworker.js" "${OUT}"

cp ${MAINGENWASM} ${OUTWASM}
cp ${OUT}/process.js ${OUTJS}
me_forked_val=$(sed -n 's/.*Module\["_me_forked"\][[:space:]]*=[[:space:]]*\([0-9]\+\).*/\1/p' ${MAINGENJS})
sed -i "s/\(var[[:space:]]\+meForkedP[[:space:]]*=[[:space:]]*\).*/\1${me_forked_val};/" ${OUTJS}
me_execved_val=$(sed -n 's/.*Module\["_me_execved"\][[:space:]]*=[[:space:]]*\([0-9]\+\).*/\1/p' ${MAINGENJS})
sed -i "s/\(var[[:space:]]\+meExecvedP[[:space:]]*=[[:space:]]*\).*/\1${me_execved_val};/" ${OUTJS}

if [[ -n "${INITWASM}" ]]; then
cp -p "${BROWSER_DIR}/js-kernel.js" "${OUT}"
cp -p "${BROWSER_DIR}/main.html" "${OUTHTML}"
sed -i "s/initProgram: '[^']*\.wasm'/initProgram: '${ELFNAME}.wasm'/" "${OUTHTML}"
fi
if [[ -f "${OUTHTML}" ]]; then
sed -i "s/var binList = \[\(.*[^ ]\)\]/var binList = [\1, \"${ELFNAME}\"]/;
s/var binList = \[\]/var binList = [\"${ELFNAME}\"]/" "${OUTHTML}"
else
echo "${OUTHTML} is not found. Please prepare init Wasm program."
exit 1
fi

if [[ -f "${OUT}/preload-manifest.json" ]]; then
echo -e "[${GREEN}INFO${NC}] Preload manifest found, copying data files."
fi

setting "$1" "$2"
rm "${OUT}/process.js"
}

main() {

mkdir -p out
setting "$1"

if [ $# -eq 0 ]; then
echo "[${RED}ERROR${NC}] target ELF binary is not specified."
echo $#
echo -e "[${RED}ERROR${NC}] target ELF binary is not specified."
exit 1
fi

# only ELF/aarch64 is supported at current release.
mkdir -p ${OUT}

if [[ -n "${READYJS}" ]]; then
prepare_js
exit 0
fi

case "$TARGET" in
aarch64-*)
RT_OP="$RT_OP -DELF_IS_AARCH64"
Expand All @@ -42,54 +87,56 @@ main() {
;;
esac

# ELF -> LLVM bc
FORK_EMULATION="0"
case "${TARGET}" in
*-wasm)
FORK_EMULATION="1"
;;
esac

echo -e "[${GREEN}INFO${NC}] Converting ELF to LLVM bitcode ..."
./bin/elflift \
./bin/elflift \
--arch aarch64 \
--bc_out ${OUT}/lift.bc \
--target_elf "$ELFPATH" \
--bitcode_path ./bitcode && \
--bitcode_path ./bitcode \
--target_arch "$(uname -p)" \
--float_exception "0" \
--norm_mode "1" \
--fork_emulation "${FORK_EMULATION}"
echo -e "[${GREEN}INFO${NC}] Generate lift.bc."

# LLVM bc -> target file
case "$TARGET" in
*-wasm)
RT_OP="$RT_OP -DTARGET_IS_BROWSER=1"
if [ -n "$MOUNTDIR" ]; then
PRELOAD="--preload-file ${MOUNTDIR}"
fi
RT_OP="$RT_OP -DTARGET_IS_BROWSER=1 -DELFNAME=\"${ELFNAME}\""
echo -e "[${GREEN}INFO${NC}] Converting LLVM bitcode to WASM binary (for browser) ..."
$EMCC $RT_OP -o ${OUT}/exe.js ${OUT}/lift.bc -L"./lib" -sWASM -sALLOW_MEMORY_GROWTH -sASYNCIFY -sEXPORT_ES6 -sENVIRONMENT=web $PRELOAD --js-library "./lib/emscripten-pty.js" -lelfconvbrowser
rm ${OUT}/lift.*
echo -e "[${GREEN}INFO${NC}] Generate WASM binary."

# specify the binary name
if [ -n "$OUT_EXE" ]; then
cp ${OUT}/exe.wasm ${OUT}/${OUT_EXE}
sed -i "s/exe\.wasm/${OUT_EXE}/g" ${OUT}/exe.js
sed -i "s/this\.program/${OUT_EXE}/g" ${OUT}/exe.js
fi
$EMCC $RT_OP ${EMCC_OPTION} -o ${OUT}/${ELFNAME}.generated.js ${OUT}/lift.bc -L"./lib" -lelfconvbrowser

# move exe.data to the current directory
if [ -e "${OUT}/exe.data" ]; then
mv "${OUT}/exe.data" .
if [[ -n "${MOUNT_SETTING}" ]]; then
echo -e "[${GREEN}INFO${NC}] Packing preload data for: ${MOUNT_SETTING}"
python3 ./scripts/pack-preload.py ${MOUNT_SETTING} -o "${OUT}"
fi

echo -e "[${GREEN}INFO${NC}] built ${ELFNAME}.wasm and ${ELFNAME}.js."

prepare_js

rm ${OUT}/lift.*
return 0
;;
*-wasi32)
RT_OP="$RT_OP -DTARGET_IS_WASI=1 ${WASISDK_COMPILEFLAGS} ${WASISDK_LINKFLAGS}"
RT_OP="$RT_OP -DTARGET_IS_WASI=1 -DELFNAME=\"${ELFNAME}\" ${WASISDK_COMPILEFLAGS}"
echo -e "[${GREEN}INFO${NC}] Converting LLVM bitcode to WASM binary (for server) ..."
$WASISDKCXX $RT_OP -o ${OUT}/exe.wasm -L"./lib" ${OUT}/lift.bc -lelfconvwasi
rm ${OUT}/lift.*
$WASISDKCXX $RT_OP ${WASISDK_LINKFLAGS} -o ${OUT}/exe.wasm -L"./lib" ${OUT}/lift.bc -lelfconvwasi
rm ${OUT}/lift.*
echo -e "[${GREEN}INFO${NC}] Generate WASM binary."
$WASMEDGE_COMPILE_OPT ${OUT}/exe.wasm ${OUT}/exe_o3.wasm
$WASMEDGE_COMPILE_OPT ${OUT}/exe.wasm ${OUT}/exe_o3.wasm
echo -e "[${GREEN}INFO${NC}] WasmEdge optimization was done. (exe_o3.wasm)"

return 0
;;
esac

}

main "$@"
main "$@"
32 changes: 0 additions & 32 deletions release/outdir/index.html

This file was deleted.

72 changes: 62 additions & 10 deletions release/release.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
#!/usr/bin/env bash
#
# Usage:
# VERSION=v0.3.0 bash release.sh
#
# Environment variables:
# VERSION (required) Release version string (e.g. v0.3.0).
# Used for the output tarball name: elfconv-<VERSION>-linux-<arch>.tar.gz
#
# Examples:
# VERSION=v0.3.0 bash release.sh # build release package and create tarball
# bash release.sh clean # remove built artifacts
#

set -e

GREEN="\033[32m"
ORANGE="\033[33m"
Expand All @@ -13,17 +27,26 @@ setting() {
ELFCONV_ARCH_DIR=${BUILD_DIR}/backend/remill/lib/Arch
RUNTIME_DIR=${ELFCONV_DIR}/runtime
UTILS_DIR=${ELFCONV_DIR}/utils
BROWSER_DIR=${ELFCONV_DIR}/browser
SCRIPTS_DIR=${ELFCONV_DIR}/scripts
OUTDIR=${RELEASE_DIR}/outdir
BINDIR=${OUTDIR}/bin
BITCODEDIR=${OUTDIR}/bitcode
LIBDIR=${OUTDIR}/lib
OUTOUTDIR=${OUTDIR}/out

HOST_ARCH=$(uname -m)
case "${HOST_ARCH}" in
x86_64) ARCH_LABEL="amd64" ;;
aarch64) ARCH_LABEL="aarch64" ;;
*) ARCH_LABEL="${HOST_ARCH}" ;;
esac

# shared compiler options
OPTFLAGS="-O3"

# emscripten
EMCXX=emcc
EMCXX=em++
EMAR=emar
EMCCFLAGS="${OPTFLAGS} -I${ELFCONV_DIR}/backend/remill/include -I${ELFCONV_DIR}"
EMCC_ELFCONV_MACROS=" -DELF_IS_AARCH64 -DTARGET_IS_BROWSER=1"
Expand All @@ -47,7 +70,7 @@ main() {

# clean existing outdir/
if [ "$1" = "clean" ]; then
rm -rf $BINDIR $BITCODEDIR $LIBDIR $OUTOUTDIR *.tar.gz
rm -rf $BINDIR $BITCODEDIR $LIBDIR $OUTOUTDIR ${OUTDIR}/browser ${OUTDIR}/scripts *.tar.gz
exit 0
fi

Expand All @@ -67,14 +90,21 @@ main() {

# set semantics *.bc file
mkdir -p $BITCODEDIR
if cp ${ELFCONV_ARCH_DIR}/AArch64/Runtime/aarch64.bc $BITCODEDIR && \
cp ${ELFCONV_ARCH_DIR}/X86/Runtime/amd64.bc $BITCODEDIR && \
cp ${ELFCONV_ARCH_DIR}/X86/Runtime/x86.bc $BITCODEDIR ; then
echo -e "[${GREEN}INFO${NC}] Set semantics *.bc."
else
echo -e "[${RED}ERROR${NC}] Failed to set semantics *.bc."
exit 1
fi
case "${ARCH_LABEL}" in
aarch64)
cp ${ELFCONV_ARCH_DIR}/AArch64/Runtime/aarch64.bc $BITCODEDIR
echo -e "[${GREEN}INFO${NC}] Set semantics aarch64.bc."
;;
amd64)
cp ${ELFCONV_ARCH_DIR}/X86/Runtime/amd64.bc $BITCODEDIR
cp ${ELFCONV_ARCH_DIR}/X86/Runtime/x86.bc $BITCODEDIR
echo -e "[${GREEN}INFO${NC}] Set semantics amd64.bc, x86.bc."
;;
*)
echo -e "[${RED}ERROR${NC}] Unsupported architecture: ${HOST_ARCH}"
exit 1
;;
esac

# prepare elfconv-runtime program.
mkdir -p $LIBDIR
Expand Down Expand Up @@ -142,6 +172,28 @@ main() {
# library of xterm-pty
cp ${ELFCONV_DIR}/xterm-pty/emscripten-pty.js $LIBDIR

BROWSEROUTDIR=${OUTDIR}/browser
mkdir -p $BROWSEROUTDIR
cp ${BROWSER_DIR}/* $BROWSEROUTDIR
echo -e "[${GREEN}INFO${NC}] Set browser files."

SCRIPTSOUTDIR=${OUTDIR}/scripts
mkdir -p $SCRIPTSOUTDIR
cp ${SCRIPTS_DIR}/pack-preload.py $SCRIPTSOUTDIR
echo -e "[${GREEN}INFO${NC}] Set pack-preload.py."

cp ${RELEASE_DIR}/README.md ${OUTDIR}/README.md
echo -e "[${GREEN}INFO${NC}] Set README.md."

if [[ -z "${VERSION}" ]]; then
echo -e "[${RED}ERROR${NC}] VERSION is not set. Usage: VERSION=v0.3.0 bash release.sh"
exit 1
fi
TARNAME="elfconv-${VERSION}-linux-${ARCH_LABEL}.tar.gz"
cd "${RELEASE_DIR}"
tar -czf "${TARNAME}" -C "${RELEASE_DIR}" outdir
echo -e "[${GREEN}INFO${NC}] Created ${TARNAME}."

}

main "$@"
Loading