• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/bash
2# Copyright (c) 2022 Huawei Device Co., Ltd.
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15TOPDIR=$(realpath "$(dirname ${BASH_SOURCE[0]})/../../../")
16
17PATH="${TOPDIR}/prebuilts/build-tools/linux-x86/bin/:${TOPDIR}/prebuilts/python/linux-x86/3.9.2/bin/:${PATH}"
18
19command -v jq &>/dev/null || { echo >&2 "jq command not found, please install by: apt install -y jq"; exit 1; }
20command -v ninja &>/dev/null || { echo >&2 "ninja command not found, please install by: apt install -y ninja-build"; exit 1; }
21
22args=()
23cfg_groups=()
24while test $# -gt 0; do
25    case "$1" in
26    -g[0-9]:*)
27        cfg_groups+=(${1:2})
28        ;;
29    --gn-args)
30        case "$2" in
31        is_asan=*);;
32        *)args+=("$1" "$2");;
33        esac
34        shift
35        ;;
36    *)
37        args+=("$1")
38        ;;
39    esac
40    shift
41done
42
43set -e
44
45# build both asan and nonasan images
46cd "${TOPDIR}"
47if [ -d out.a ]; then
48    if [ -d out ]; then
49        mv out out.n
50    fi
51    mv out.a out
52fi
53./build.sh "${args[@]}" --gn-args is_asan=true
54mv out out.a
55if [ -d out.n ]; then
56    mv out.n out
57fi
58./build.sh "${args[@]}" --gn-args is_asan=false
59
60
61asan_dir=$(ls -d out.a/*/packages/phone/)
62nonasan_dir=$(ls -d out/*/packages/phone/)
63
64asan_dir=$(realpath "$asan_dir")
65nonasan_dir=$(realpath "$nonasan_dir")
66
67echo "asan dir is $asan_dir"
68echo "non-asan dir is $nonasan_dir"
69
70# check directories
71for d in {"$asan_dir","$nonasan_dir"}/{system,vendor,data} ; do
72    if [ ! -d "$d" ]; then
73        echo "directory '$d' does not exist."
74        exit 1
75    fi
76done
77
78# following works should all be done in nonasan dir
79pushd "$nonasan_dir"
80
81handle_error() {
82    if [ "$?" -ne 0 ]; then
83        set +e
84        pushd "$nonasan_dir"
85        test -d system.bak && rm -rf system && mv system.bak system
86        test -d vendor.bak && rm -rf vendor && mv vendor.bak vendor
87        test -d images.bak && rm -rf images && mv images.bak images
88    fi
89}
90trap handle_error EXIT
91
92# get make image command
93json_data="$(ninja -C ../../ -t compdb | jq '.[]|select(.output|startswith("packages/phone/images/"))')"
94make_system_img_cmd="$(echo "$json_data" | jq -r 'select(.output=="packages/phone/images/system.img")|.command')"
95make_vendor_img_cmd="$(echo "$json_data" | jq -r 'select(.output=="packages/phone/images/vendor.img")|.command')"
96make_userdata_img_cmd="$(echo "$json_data" | jq -r 'select(.output=="packages/phone/images/userdata.img")|.command')"
97make_system_img() { pushd ../../; $make_system_img_cmd; popd; }
98make_vendor_img() { pushd ../../; $make_vendor_img_cmd; popd; }
99make_userdata_img() { pushd ../../; $make_userdata_img_cmd; popd; }
100
101make_mixed_asan_img() {
102    cfg_group=(${@:2})
103
104    # backup system and vendor
105    mv system system.bak && cp -a system.bak system
106    mv vendor vendor.bak && cp -a vendor.bak vendor
107
108    # prepare asan related files for system image
109    cp -a "$asan_dir"/system/etc/asan.options system/etc/
110    cp -a "$asan_dir"/system/etc/init/asan.cfg system/etc/init/
111    cp -a "$asan_dir"/system/lib/ld-musl-*-asan.so.1 system/lib/
112    cp -a "$asan_dir"/system/etc/ld-musl-*-asan.path system/etc/
113    sed -i 's,/system/\([^:]*\),/data/\1:&,g' system/etc/ld-musl-*-asan.path
114
115    # make some services run in asan version
116    local make_system=false
117    local make_vendor=false
118    for f in ${cfg_group[@]/%/.cfg}; do
119        if [ -f system/etc/init/$f ]; then
120            echo "$f is found in /system/etc/init/"
121            sed -i 's,/system/bin/,/data/bin/,g' system/etc/init/$f
122            sed -i '/"critical"/d' system/etc/init/$f
123            for xml in $(sed -n '/\/data\/bin\/sa_main/s/.*"\([^" ]*.xml\)".*/\1/p' system/etc/init/$f); do
124                sed -i 's,/system/\(lib[^/]*\)/,/data/\1/,g' ./$xml
125            done
126            make_system=true
127        elif [ -f vendor/etc/init/$f ]; then
128            echo "$f is found in /vendor/etc/init/"
129            sed -i 's,/vendor/bin/,/data/bin/,g' vendor/etc/init/$f
130            sed -i 's,/system/bin/,/data/bin/,g' vendor/etc/init/$f
131            sed -i '/"critical"/d' vendor/etc/init/$f
132            for xml in $(sed -n '/\/data\/bin\/sa_main/s/.*"\([^" ]*.xml\)".*/\1/p' vendor/etc/init/$f); do
133                sed -i 's,/vendor/\(lib[^/]*\)/,/data/\1/,g' ./$xml
134                sed -i 's,/system/\(lib[^/]*\)/,/data/\1/,g' ./$xml
135            done
136            make_vendor=true
137        else
138            echo -e "\033[33m==== WARNING: $f is not found in /system/etc/init/ nor in /vendor/etc/init/ ====\033[0m"
139        fi
140    done
141
142    # make image
143    if [ "$make_system" = true -o $# -eq 0 ]; then
144        make_system_img
145        mv images/system.img system${1}.img
146    fi
147    if [ "$make_vendor" = true ]; then
148        make_vendor_img
149        mv images/vendor.img vendor${1}.img
150    fi
151
152    # restore system and vendor
153    rm -rf system && mv system.bak system
154    rm -rf vendor && mv vendor.bak vendor
155}
156
157add_mkshrc() {
158    sed -i '/export HOME /d' "$asan_dir"/system/etc/init/asan.cfg
159    sed -i '/export ASAN_OPTIONS /i"export HOME /data",' "$asan_dir"/system/etc/init/asan.cfg
160    cat <<EOF >${1:-.}/.mkshrc
161dmesg -n1
162alias ls='ls --color=auto'
163alias ll='ls -al'
164remount() {
165    mount -o remount,rw \${1:-/}
166}
167EOF
168}
169
170# $1   file that need to be patched
171# $2   file offset
172# $3   instruction count, 4 bytes per instruction on arm architecture
173patch_file_nop() {
174    while true; do echo -e -n "\x1F\x20\x03\xD5"; done | dd conv=notrunc bs=1 of=$1 seek=$2 count=$((4*$3))
175}
176
177make_data_asan_img() {
178    cp -a "$asan_dir"/vendor/{lib*,bin} data/
179    cp -a "$asan_dir"/system/{lib*,bin} data/
180    add_mkshrc data/
181    sed -i.bak 's,shutil.rmtree(userdata_path),return,g' "${TOPDIR}"/build/ohos/images/build_image.py
182    sed -i.bak '$adata/bin/*, 00755, 0, 2000, 0' "${TOPDIR}"/build/ohos/images/mkimage/dac.txt
183    if [ -f data/lib64/libclang_rt.asan.so ]; then
184        if [ "$(md5sum data/lib64/libclang_rt.asan.so|awk '{print $1}')" = "e4ade6eb02f6bbbd7f7faebcda3f0a26" ]; then
185            patch_file_nop data/lib64/libclang_rt.asan.so 356872 17 # patch function 'GetThreadStackAndTls'
186        fi
187    fi
188    make_userdata_img
189    mv "${TOPDIR}"/build/ohos/images/mkimage/dac.txt.bak "${TOPDIR}"/build/ohos/images/mkimage/dac.txt
190    mv "${TOPDIR}"/build/ohos/images/build_image.py.bak "${TOPDIR}"/build/ohos/images/build_image.py
191}
192
193make_custom_asan_imgs() {
194    # backup images
195    mv images images.bak && mkdir images
196
197    # make custom asan images
198    for cfg_group in ${cfg_groups[@]}; do
199        local OLDIFS="$IFS"
200        IFS+=":,"
201        make_mixed_asan_img ${cfg_group}
202        IFS="$OLDIFS"
203    done
204
205    # restore images
206    rm -rf images && mv images.bak images
207}
208
209make_data_asan_img
210make_mixed_asan_img
211make_custom_asan_imgs
212
213shopt -s nullglob && mv system*.img vendor*.img images/
214
215echo -e "\033[32m==== Done! ====\033[0m"
216popd
217