1#!/bin/bash
2#
3#   honggfuzz libunwind build help script
4#   -----------------------------------------
5#
6#   Licensed under the Apache License, Version 2.0 (the "License");
7#   you may not use this file except in compliance with the License.
8#   You may obtain a copy of the License at
9#
10#     http://www.apache.org/licenses/LICENSE-2.0
11#
12#   Unless required by applicable law or agreed to in writing, software
13#   distributed under the License is distributed on an "AS IS" BASIS,
14#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15#   See the License for the specific language governing permissions and
16#   limitations under the License.
17
18if [ -z "$NDK" ]; then
19  # Search in $PATH
20  if [[ $(which ndk-build) != "" ]]; then
21    NDK=$(dirname $(which ndk-build))
22  else
23    echo "[-] Could not detect Android NDK dir"
24    exit 1
25  fi
26fi
27
28if [ $# -ne 2 ]; then
29  echo "[-] Invalid arguments"
30  echo "[!] $0 <LIBUNWIND_DIR> <ARCH>"
31  echo "    ARCH: arm arm64 x86 x86_64"
32  exit 1
33fi
34
35readonly LIBUNWIND_DIR=$1
36
37# Fetch if not already there
38if [ ! -d $LIBUNWIND_DIR ]; then
39    echo "[!] libunwind not found. Fetching a fresh copy"
40    git clone git://git.sv.gnu.org/libunwind.git $LIBUNWIND_DIR
41fi
42
43case "$2" in
44  arm|arm64|x86|x86_64)
45    readonly ARCH=$2
46    if [ ! -d $LIBUNWIND_DIR/$ARCH ] ; then mkdir -p $LIBUNWIND_DIR/$ARCH; fi
47    ;;
48  *)
49    echo "[-] Invalid architecture"
50    exit 1
51    ;;
52esac
53
54LC_LDFLAGS="-static"
55
56# For debugging
57# Remember to export UNW_DEBUG_LEVEL=<level>
58# where 1 < level < 16 (usually values up to 5 are enough)
59#LC_CFLAGS="$LC_FLAGS -DDEBUG"
60
61# Change workdir to simplify args
62cd $LIBUNWIND_DIR
63
64# Prepare toolchain
65case "$ARCH" in
66  arm)
67    TOOLCHAIN=arm-linux-androideabi
68    TOOLCHAIN_S=arm-linux-androideabi-4.9
69    ;;
70  arm64)
71    TOOLCHAIN=aarch64-linux-android
72    TOOLCHAIN_S=aarch64-linux-android-4.9
73    ;;
74  x86)
75    TOOLCHAIN=i686-linux-android
76    TOOLCHAIN_S=x86-4.9
77    ;;
78  x86_64)
79    TOOLCHAIN=x86_64-linux-android
80    TOOLCHAIN_S=x86_64-4.9
81    ;;
82esac
83
84# Apply patches required for Android
85# TODO: Automate global patching when all archs have been tested
86
87# Ptrace patches due to Android incompatibilities
88patch -N --dry-run --silent src/ptrace/_UPT_access_reg.c < ../patches/ptrace-libunwind_1.patch &>/dev/null
89if [ $? -eq 0 ]; then
90  patch src/ptrace/_UPT_access_reg.c < ../patches/ptrace-libunwind_1.patch
91  if [ $? -ne 0 ]; then
92    echo "[-] ptrace-libunwind_1 patch failed"
93    exit 1
94  fi
95fi
96
97patch -N --dry-run --silent src/ptrace/_UPT_access_fpreg.c < ../patches/ptrace-libunwind_2.patch &>/dev/null
98if [ $? -eq 0 ]; then
99  patch src/ptrace/_UPT_access_fpreg.c < ../patches/ptrace-libunwind_2.patch
100  if [ $? -ne 0 ]; then
101    echo "[-] ptrace-libunwind_2 patch failed"
102    exit 1
103  fi
104fi
105
106if [ "$ARCH" == "arm64" ]; then
107  # Missing libc functionality
108  patch -N --dry-run --silent include/libunwind-aarch64.h < ../patches/aarch64-libunwind_1.patch &>/dev/null
109  if [ $? -eq 0 ]; then
110    patch include/libunwind-aarch64.h < ../patches/aarch64-libunwind_1.patch
111    if [ $? -ne 0 ]; then
112      echo "[-] aarch64-libunwind_1 patch failed"
113      exit 1
114    fi
115  fi
116  # Frames ip bugs
117  patch -N --dry-run --silent src/aarch64/Gstep.c < ../patches/aarch64-libunwind_2.patch &>/dev/null
118  if [ $? -eq 0 ]; then
119    patch src/aarch64/Gstep.c < ../patches/aarch64-libunwind_2.patch
120    if [ $? -ne 0 ]; then
121      echo "[-] aarch64-libunwind_2 patch failed"
122      exit 1
123    fi
124  fi
125fi
126
127if [ "$ARCH" == "x86" ]; then
128  # Missing syscalls
129  patch -N --dry-run --silent src/x86/Gos-linux.c < ../patches/x86-libunwind.patch &>/dev/null
130  if [ $? -eq 0 ]; then
131    patch src/x86/Gos-linux.c < ../patches/x86-libunwind.patch
132    if [ $? -ne 0 ]; then
133      echo "[-] x86-libunwind patch failed"
134      exit 1
135    fi
136  fi
137fi
138
139# Support both Linux & Darwin
140HOST_OS=$(uname -s | tr '[:upper:]' '[:lower:]')
141HOST_ARCH=$(uname -m)
142
143SYSROOT="$NDK/platforms/android-21/arch-$ARCH"
144export CC="$NDK/toolchains/$TOOLCHAIN_S/prebuilt/$HOST_OS-$HOST_ARCH/bin/$TOOLCHAIN-gcc --sysroot=$SYSROOT"
145export CXX="$NDK/toolchains/$TOOLCHAIN_S/prebuilt/$HOST_OS-$HOST_ARCH/bin/$TOOLCHAIN-g++ --sysroot=$SYSROOT"
146export PATH="$NDK/toolchains/$TOOLCHAIN_S/prebuilt/$HOST_OS-$HOST_ARCH/bin":$PATH
147
148if [ ! -f configure ]; then
149  autoreconf -i
150  if [ $? -ne 0 ]; then
151    echo "[-] autoreconf failed"
152    exit 1
153  fi
154  # Patch configure
155  sed -i -e 's/-lgcc_s/-lgcc/g' configure
156else
157  make clean
158fi
159
160./configure --host=$TOOLCHAIN --disable-coredump
161if [ $? -ne 0 ]; then
162  echo "[-] configure failed"
163  exit 1
164fi
165
166# Fix stuff that configure failed to detect
167# TODO: Investigate for more elegant patches
168if [ "$ARCH" == "arm64" ]; then
169  sed -i -e 's/#define HAVE_DECL_PTRACE_POKEUSER 1/#define HAVE_DECL_PTRACE_POKEUSER 0/g' include/config.h
170  echo "#define HAVE_DECL_PT_GETREGSET 1" >> include/config.h
171fi
172
173make CFLAGS="$LC_CFLAGS" LDFLAGS="$LC_LDFLAGS"
174if [ $? -ne 0 ]; then
175    echo "[-] Compilation failed"
176    cd - &>/dev/null
177    exit 1
178else
179    echo "[*] '$ARCH' libunwind  available at '$LIBUNWIND_DIR/$ARCH'"
180    cp src/.libs/*.a $ARCH
181    cd - &>/dev/null
182fi
183