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