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