1#! /bin/bash -eu 2 3# This script prints linker trace for a given ELF file. 4# It extracts the command that has built this ELF file from the 5# build log (verbose.log.gz file in the given output directory), 6# appends `-t` linker option to it in order to print its source 7# files and runs this command 8# This script can be used when we want to compare ELF executables 9# built by two different configurations (e.g., conventional and mixed 10# builds). In this case, we run the build for one configuration, then 11# rename `out` directory to something else, and then run the build 12# for another configuration. To accommodate this scenario, an optional 13# second argument specifies the renamed output directory. The linker 14# command then runs inside nsjail that maps the renamed output 15# directory to `out`. 16 17function die() { format=$1; shift; printf >&2 "$format\n" $@; exit 1; } 18function usage() { 19 die "usage: ${0##*/} [-v] ELF [DIR]" 20} 21 22# Delouse 23declare show_command= 24while getopts "v" opt; do 25 case $opt in 26 v) show_command=t ;; 27 *) usage ;; 28 esac 29done 30shift $(($OPTIND-1)) 31(($# >= 1)) || usage 32 33declare -r elf="$1"; shift 34declare -r outdir="${1:-out}" 35[[ -d "$outdir" ]] || die "$outdir does not exist" 36[[ -f "$outdir/verbose.log.gz" ]] || \ 37 die "$outdir does not contain Android build (verbose.log.gz is missing)" 38 39function zgrep_command() { 40 zgrep -e "bin/clang\+\+.* -o [^ ]*$elf " $outdir/verbose.log.gz 41} 42 43# Locate the command that builds this ELF file and write it to 44# the temporary file editing it on the way: 45# * remove step number (`[nn/NN]`) prefix 46# * linker should write to the bit bucket 47# * add `-Wl,-t` (linker's `-t` option) 48cmdfile=$(mktemp); trap 'rm -f $cmdfile' EXIT 49zgrep_command |\ 50 sed -r 's| -o ([^ ]+) | -Wl,-t -o /dev/null |;s|^\[.*\]||' > $cmdfile 51[[ -z "${show_command}" ]] || cat $cmdfile >&2 52[[ -s $cmdfile ]] || die "no ELF file ending with $elf was built in $outdir" 53(($(wc -l $cmdfile | cut -f1 -d ' ') == 1)) || \ 54 { printf >&2 "Multiple elf files ending with $elf were built in $outdir:\n"; 55 die " %s" $(zgrep_command | sed -r 's|.* -o ([^ ]+) .*|\1|'); } 56 57# Run the linker (i.e., the command we have written into $cmdfile). Its output 58# is the list of the object files it read. If output directory has been renamed, 59# run it inside `nsjail`, mapping output directory ot `out/` 60if [[ "$outdir" == out ]]; then 61 /bin/bash $cmdfile 62else 63 prebuilts/build-tools/linux-x86/bin/nsjail \ 64 -Mo -q -e -t 0 -B / -B /tmp -B $(realpath $outdir):$PWD/out \ 65 --cwd $PWD --skip_setsid --keep_caps --disable_clone_newcgroup --disable_clone_newnet \ 66 --rlimit_as soft --rlimit_core soft --rlimit_cpu soft --rlimit_fsize soft --rlimit_nofile soft \ 67 --proc_rw --hostname "$(hostname)" -- /bin/bash $cmdfile 68fi 69