├── .dockerignore ├── .gitignore ├── Makefile ├── Dockerfile ├── README.md ├── ollvm-build.sh └── ollvm-add-to-ndk.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | .tmp/ 2 | android-ndk-r* 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .tmp/ 3 | android-ndk-r* 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DOCKER = docker 2 | IMAGE = nickdiego/ollvm-build 3 | 4 | build: Dockerfile 5 | $(DOCKER) build -t $(IMAGE) . 6 | 7 | push: build 8 | $(DOCKER) push $(IMAGE):latest 9 | 10 | all: push 11 | 12 | .PHONY: all 13 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | #===- llvm/utils/docker/debian8/build/Dockerfile -------------------------===// 2 | # 3 | # The LLVM Compiler Infrastructure 4 | # 5 | # This file is distributed under the University of Illinois Open Source 6 | # License. See LICENSE.TXT for details. 7 | # 8 | #===----------------------------------------------------------------------===// 9 | # Produces an image that compiles and archives clang, based on debian8. 10 | # Based on official Dockerfile example: https://llvm.org/docs/Docker.html 11 | #===----------------------------------------------------------------------===// 12 | 13 | FROM launcher.gcr.io/google/debian8:latest 14 | 15 | LABEL maintainer Nick Yamane 16 | 17 | # Install build dependencies of llvm. 18 | # First, Update the apt's source list and include the sources of the packages. 19 | RUN grep deb /etc/apt/sources.list | \ 20 | sed 's/^deb/deb-src /g' >> /etc/apt/sources.list 21 | 22 | # Install compiler, python and subversion. 23 | RUN apt-get update && \ 24 | apt-get install -y --no-install-recommends ca-certificates gnupg \ 25 | build-essential python wget subversion unzip && \ 26 | rm -rf /var/lib/apt/lists/* 27 | 28 | # Install a newer ninja release. It seems the older version in the debian repos 29 | # randomly crashes when compiling llvm. 30 | RUN wget "https://github.com/ninja-build/ninja/releases/download/v1.8.2/ninja-linux.zip" && \ 31 | echo "d2fea9ff33b3ef353161ed906f260d565ca55b8ca0568fa07b1d2cab90a84a07 ninja-linux.zip" \ 32 | | sha256sum -c && \ 33 | unzip ninja-linux.zip -d /usr/local/bin && \ 34 | rm ninja-linux.zip 35 | 36 | # Import public key required for verifying signature of cmake download. 37 | RUN gpg --keyserver hkp://pgp.mit.edu --recv 0x2D2CEF1034921684 38 | 39 | # Download, verify and install cmake version that can compile clang into /usr/local. 40 | # (Version in debian8 repos is is too old) 41 | RUN mkdir /tmp/cmake-install && cd /tmp/cmake-install && \ 42 | wget "https://cmake.org/files/v3.7/cmake-3.7.2-SHA-256.txt.asc" && \ 43 | wget "https://cmake.org/files/v3.7/cmake-3.7.2-SHA-256.txt" && \ 44 | gpg --verify cmake-3.7.2-SHA-256.txt.asc cmake-3.7.2-SHA-256.txt && \ 45 | wget "https://cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz" && \ 46 | ( grep "cmake-3.7.2-Linux-x86_64.tar.gz" cmake-3.7.2-SHA-256.txt | \ 47 | sha256sum -c - ) && \ 48 | tar xzf cmake-3.7.2-Linux-x86_64.tar.gz -C /usr/local --strip-components=1 && \ 49 | cd / && rm -rf /tmp/cmake-install 50 | 51 | ADD ollvm-*.sh /scripts/ 52 | 53 | ENV OLLVM_DIR /ollvm/src 54 | 55 | VOLUME [ "/ollvm/src" ] 56 | 57 | CMD [ "/scripts/ollvm-build.sh", "--docker" ] 58 | 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Dockerized build and helper scripts for Obfuscator-LLVM 2 | 3 | This repository provides a Dockerfile and some helper shell scripts useful to easily build Obfuscator-LLVM project from source as well as configuring it as a Android NDK toolchain. The scripts can be used both as standalone tools and inside the Docker image. 4 | 5 | #### Prerequisites 6 | 7 | - Bash 8 | - Docker (_ideally [configured to be executed as non-root user](https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user)_) 9 | 10 | #### Basic usage 11 | 12 | - Build O-LLVM within a docker container, using `ollvm/source/dir` as source directory 13 | The output build directory will be in `ollvm/source/dir/build_docker`. 14 | ```bash 15 | ./ollvm-build.sh ollvm/source/dir 16 | ``` 17 | 18 | - Add O-LLVM toolchain into Official Android NDK, using `ollvm/artifacts/dir` as binary directory 19 | (result from a previous OLLVM build). The output NDK package will be generated into the current 20 | working directory. 21 | ```bash 22 | ./ollvm-add-to-ndk.sh ollvm/artifacts/dir 23 | ``` 24 | 25 | #### Using in Gitlab-CI 26 | 27 | Another use case where these scripts are very useful is to integrate O-LLVM build process into a Continuous Integration 28 | system, which is very handy when researching/hacking O-LLVM (E.g: Adding some experimental features or improving 29 | the existing ones). 30 | Below is an example on how to build O-LLVM and generate a NDK with O-LLVM toolchain using the docker image built from this repository: 31 | 32 | ```yaml 33 | ... 34 | build: 35 | stage: build 36 | script: 37 | ┆ - OLLVM_DIR=$PWD /scripts/ollvm-build.sh --docker 38 | ┆ - tar -cfz ollvm-4.0.tgz build_docker/_installed_/* 39 | artifacts: 40 | ┆ paths: 41 | ┆ ┆ - ollvm-4.0.tgz 42 | stage: build 43 | 44 | package: 45 | stage: repackage_ndk 46 | script: 47 | ┆ - /scripts/ollvm-add-to-ndk.sh build_docker/_installed_ 48 | artifacts: 49 | ┆ paths: 50 | ┆ ┆ - android-ndk-r14b-ollvm4.0-linux-x86_64.tar.gz 51 | ... 52 | ``` 53 | 54 | #### About Obfuscator-LLVM 55 | 56 | O-LLVM is an open-source fork of the LLVM compilation suite able to provide increased software security through code obfuscation and tamper-proofing. As we currently mostly work at the Intermediate Representation (IR) level, our tool is compatible with all programming languages (C, C++, Objective-C, Ada and Fortran) and target platforms (x86, x86-64, PowerPC, PowerPC-64, ARM, Thumb, SPARC, Alpha, CellSPU, MIPS, MSP430, SystemZ, and XCore) currently supported by LLVM. 57 | 58 | More information: https://github.com/obfuscator-llvm/obfuscator/wiki 59 | 60 | 61 | #### Docker Hub 62 | 63 | https://hub.docker.com/r/nickdiego/ollvm-build/ 64 | 65 | -------------------------------------------------------------------------------- /ollvm-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # vim: ts=2 sw=2 3 | # 4 | # Helper script for building Obfuscator-LLVM in a Docker container 5 | # 6 | # Copyright (c) 2017 Nick Diego Yamane 7 | # 8 | # This program is free software; you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation; either version 2 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | 21 | set -e 22 | 23 | function show_usage() { 24 | cat << EOF 25 | Usage: ollvm-build.sh 26 | 27 | Build a volume-mapped local Obfuscator-LLVM inside docker container. 28 | If no arguments are given, 'bash' is executed in the build container 29 | instead of the build script. 30 | 31 | Available options: 32 | -h|--help show this help message 33 | -b|--build-only run only the build step (do not install) 34 | 35 | Positional arguments: 36 | path/to/ollvm/src the O-LLVM source directory path 37 | 38 | All options after '--' are passed to CMake invocation. 39 | EOF 40 | } 41 | 42 | # In docker-mode should be set in Dockerfile 43 | # In host-mode, set using command-line arg 44 | OLLVM_DIR=${OLLVM_DIR:-} 45 | DOCKER_MODE=0 46 | BUILD_ONLY=0 47 | 48 | BUILD_DIR_NAME='build' 49 | INSTALL_DIR_NAME='_installed_' 50 | 51 | declare -a CMAKE_ARGS 52 | declare -a FWD_ARGS 53 | 54 | # Process command line arguments 55 | while [ $# -gt 0 ]; do 56 | case "$1" in 57 | --) 58 | shift 59 | ;; 60 | -d|--docker) 61 | DOCKER_MODE=1 62 | shift 63 | ;; 64 | -b|--build-only) 65 | BUILD_ONLY=1 66 | shift 67 | ;; 68 | -h|--help) 69 | show_usage 70 | exit 0 71 | ;; 72 | *) 73 | if [ -d "$1" ]; then 74 | OLLVM_DIR=$(readlink -f $1) 75 | shift 76 | else 77 | CMAKE_ARGS+=( "$@" ) 78 | shift $# 79 | fi 80 | esac 81 | done 82 | 83 | # Process CMAKE_ARGS and generate build vars: 84 | # BUILD_TYPE, BUILD_DIR, INSTALL_DIR 85 | BUILD_TYPE=${BUILD_TYPE:-Release} 86 | CMAKE_ARGS_HAVE_BUILD_TYPE=0 87 | 88 | for i in ${CMAKE_ARGS[@]}; do 89 | if grep "^-DCMAKE_BUILD_TYPE=" <<< "$i"; then 90 | CMAKE_ARGS_HAVE_BUILD_TYPE=1 91 | BUILD_TYPE="${i#-DCMAKE_BUILD_TYPE=}" 92 | break 93 | fi 94 | done 95 | (( CMAKE_ARGS_HAVE_BUILD_TYPE )) || CMAKE_ARGS+=( "-DCMAKE_BUILD_TYPE=${BUILD_TYPE}" ) 96 | 97 | BUILD_DIR="${OLLVM_DIR}/${BUILD_DIR_NAME}_${BUILD_TYPE,,}" 98 | INSTALL_DIR="${BUILD_DIR}/${INSTALL_DIR_NAME}" 99 | 100 | if (( DOCKER_MODE )); then 101 | 102 | # Checking source folder sanity-check 103 | if [ ! -f "$OLLVM_DIR/llvm.spec.in" ]; then 104 | echo "Invalid O-LLVM source dir. Aborting..." 105 | exit 1 106 | fi 107 | 108 | mkdir -p "$BUILD_DIR" 109 | cd "$BUILD_DIR" 110 | 111 | if [ ! -f 'build.ninja' ]; then 112 | # FIXME: -DCMAKE_INSTALL_PREFIX not supported in DOCKER_MODE=0 113 | # Currently it's always overwritten with BUILD_DIR/INSTALL_DIR_NAME 114 | CMAKE_ARGS+=( "-DCMAKE_INSTALL_PREFIX='$INSTALL_DIR'" ) 115 | 116 | echo "Running cmake" 117 | cmake -GNinja "${CMAKE_ARGS[@]}" "$OLLVM_DIR" 118 | fi 119 | 120 | ninja -j3 121 | if (( BUILD_ONLY )); then 122 | echo "Build done!" 123 | exit 0 124 | fi 125 | 126 | ninja install 127 | # TODO pakage install dir 128 | 129 | else # script called from host 130 | 131 | (( BUILD_ONLY )) && FWD_ARGS+=( --build-only ) 132 | 133 | if [ -z $OLLVM_DIR ]; then 134 | echo "O-LLVM source dir not set. Entering in bash mode.." 135 | show_usage 136 | DOCKER_CMD='bash' 137 | else 138 | DOCKER_CMD="/scripts/ollvm-build.sh --docker ${FWD_ARGS[*]} ${CMAKE_ARGS:+-- ${CMAKE_ARGS[*]}}" 139 | fi 140 | 141 | DOCKER_IMAGE_NAME='nickdiego/ollvm-build' 142 | DOCKER_CONTAINER_NAME='ollvm-build' 143 | DOCKER_OPTS=( '--name' $DOCKER_CONTAINER_NAME --rm -v "$OLLVM_DIR:/ollvm/src" ) 144 | 145 | echo "##" 146 | echo "## Starting O-LLVM build.." 147 | echo "## Source dir : $OLLVM_DIR" 148 | echo "## Docker image: $DOCKER_IMAGE_NAME" 149 | echo "##" 150 | docker run "${DOCKER_OPTS[@]}" -it $DOCKER_IMAGE_NAME $DOCKER_CMD 151 | echo "Build finished successfully. Output directory: $BUILD_DIR" 152 | fi 153 | -------------------------------------------------------------------------------- /ollvm-add-to-ndk.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # vim: ts=2 sw=2 3 | # 4 | # Helper script for integrating and packaging O-LLVM toolchain into 5 | # official Android NDK. 6 | # 7 | # Copyright (c) 2017 Nick Diego Yamane 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | set -e 23 | 24 | function show_usage() { 25 | cat << EOF 26 | Usage: ollvm-add-to-ndk.sh [options] 27 | 28 | Build a volume-mapped local Obfuscator-LLVM inside docker container. 29 | 30 | Available options: 31 | -h|--help show this help message 32 | -n|--ndk-version Android NDK version (Supported versions: r12b, r13b, r14b) 33 | -z|--no-gzip Do not compress NDK using gzip 34 | 35 | Manadatory arguments: 36 | ollvm/binaries/path the path for the O-LLVM installation dir or tar.gz package 37 | EOF 38 | } 39 | 40 | OLLVM_DIR=${OLLVM_DIR:-} 41 | NDK_VERSION=${NDK_VERSION:-r14b} 42 | GZIP_NDK=${GZIP_NDK:-1} # TODO move to command line option 43 | 44 | TMP_DIR=$(readlink -f .tmp) # TODO suport cmdline option to overwrite this? 45 | OUT_DIR=$PWD 46 | 47 | # Process command line arguments 48 | while [ $# -gt 0 ]; do 49 | case "$1" in 50 | -h|--help) 51 | show_usage 52 | exit 0 53 | ;; 54 | -n|--ndk-version) 55 | shift && NDK_VERSION=$1 56 | ;; 57 | -z|--no-gzip) 58 | GZIP_NDK=0 59 | ;; 60 | *) 61 | OLLVM_DIR=$(readlink -f $1) 62 | esac 63 | shift 64 | done 65 | 66 | # Initialize and validate NDK variables 67 | NDK_DIR_NAME="android-ndk-${NDK_VERSION}" 68 | NDK_FILE_NAME="${NDK_DIR_NAME}-linux-x86_64.zip" 69 | NDK_DOWNLOAD_URL="https://dl.google.com/android/repository/${NDK_FILE_NAME}" 70 | NDK_FILE_PATH="$TMP_DIR/$NDK_FILE_NAME" 71 | NDK_DIR_PATH="$TMP_DIR/$NDK_DIR_NAME" 72 | 73 | NDK_SHA1_r12b='170a119bfa0f0ce5dc932405eaa3a7cc61b27694' 74 | NDK_SHA1_r13b='0600157c4ddf50ec15b8a037cfc474143f718fd0' 75 | NDK_SHA1_r14b='becd161da6ed9a823e25be5c02955d9cbca1dbeb' 76 | NDK_SHA1=$(eval "echo \$NDK_SHA1_${NDK_VERSION}") 77 | 78 | if [ -z $NDK_SHA1 ]; then 79 | echo "Unsupported NDK_VERSION '$NDK_VERSION'" 80 | echo 81 | show_usage 82 | exit 1 83 | fi 84 | 85 | # Initialize and validate O-LLVM variables 86 | if [ -z $OLLVM_DIR ] || [ ! -d $OLLVM_DIR ] || [ ! -e ${OLLVM_DIR}/bin/clang ]; then 87 | echo "Error: invalid OLLVM_DIR: '$OLLVM_DIR'" 88 | echo 89 | show_usage 90 | exit 1 91 | fi 92 | 93 | CLANG_PATH="${OLLVM_DIR}/bin/clang" 94 | OLLVM_VERSION=$($CLANG_PATH -v 2>&1 | head -n1 | sed 's|^.\+clang version \([^ ]\+\).\+$|\1|g') 95 | NDK_MODIFIED_DIR_NAME="${NDK_DIR_NAME}-ollvm${OLLVM_VERSION}" 96 | OUT_FILE="${OUT_DIR}/${NDK_MODIFIED_DIR_NAME}-linux-x86_64.tar.gz" 97 | 98 | echo "##" 99 | echo "## Starting NDK packaging.." 100 | echo "## O-LLVM directory: $OLLVM_DIR" 101 | echo "## O-LLVM Version : $OLLVM_VERSION" 102 | echo "## NDK Version : $NDK_VERSION" 103 | echo "##" 104 | 105 | mkdir -p $TMP_DIR 106 | cd $TMP_DIR 107 | 108 | # Move this to Dockerfile/image(?) 109 | if [ ! -f $NDK_FILE_PATH ]; then 110 | echo "Downloading Official NDK ${NDK_VERSION}.." 111 | wget $NDK_DOWNLOAD_URL 112 | fi 113 | 114 | if ! echo "$NDK_SHA1 $NDK_FILE_NAME" | sha1sum -c; then 115 | echo "NDK Signature check failed!" 116 | exit 1 117 | fi 118 | 119 | if [ -e $NDK_DIR_PATH ]; then 120 | echo "Removing old NDK directory.." 121 | rm -rf $NDK_DIR_PATH 122 | fi 123 | 124 | echo "Unzipping NDK files into ${PWD}" 125 | unzip -q $NDK_FILE_NAME 126 | 127 | ndk_toolchains_config_dir="build/core/toolchains" 128 | toolchain_name="ollvm${OLLVM_VERSION}" 129 | prebuilt_dir="toolchains/$toolchain_name/prebuilt/linux-x86_64/" 130 | setup_mk_regex="s|get-toolchain-root,llvm|get-toolchain-root,${toolchain_name}|g" 131 | 132 | echo "Modifying NDK.." 133 | cd $NDK_DIR_PATH 134 | mkdir -pv $prebuilt_dir 135 | cp -rfv ${OLLVM_DIR}/* ${prebuilt_dir} 136 | 137 | for config_dir in ${ndk_toolchains_config_dir}/*-clang; do 138 | new_config_dir="${config_dir}-${toolchain_name}" 139 | echo -n "Configuring toolchain ${new_config_dir} .. " 140 | cp -rf $config_dir $new_config_dir 141 | sed -i "$setup_mk_regex" "$new_config_dir/setup.mk" 142 | echo done 143 | done 144 | 145 | cd $TMP_DIR 146 | test -d $NDK_MODIFIED_DIR_NAME && rm -rf $NDK_MODIFIED_DIR_NAME 147 | cp -r $NDK_DIR_NAME $NDK_MODIFIED_DIR_NAME 148 | 149 | if (( GZIP_NDK )); then 150 | echo "Packaging modified NDK into $OUT_FILE" 151 | tar -czf $OUT_FILE $NDK_MODIFIED_DIR_NAME 152 | else 153 | echo "Generated modified NDK into ${OUT_DIR}/${NDK_MODIFIED_DIR_NAME}" 154 | mv $NDK_MODIFIED_DIR_NAME $OUT_DIR 155 | fi 156 | 157 | # TODO Generate package checksum/signature? 158 | 159 | echo "Done" 160 | --------------------------------------------------------------------------------