blob: fdde457b384d8bc21acddabd9dd5456532b190b7 [file] [log] [blame]
#!/bin/bash
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#### CATEGORY=Diagnostic
### Dumps disassembly for binaries from the build.
## usage: fx dis [-l | -S | -n | -L | -P <path to objdump>] BINARY...
##
## Dump disassembly for a binary to a file in the build directory.
##
## -l list source locations interleaved with assembly
## -S list source code lines interleaved with assembly
## -r list relocations interleaved with assembly
## -n do not demangle symbol names
## -L use llvm-objdump rather than GNU objdump
## -P <path> use objdump binary in argument
##
## Each BINARY can be the name of the binary file without directory, e.g.
## "libzircon.so" or "zircon.elf"; or the name of a GN target, e.g. "zircon";
## or a string of (lowercase) hex characters that's an ELF build ID.
##
## The disassembly will be written to a file next to the binary file in
## the build directory, using its name with ".lst" suffix.
set -o errexit
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/../lib/vars.sh || exit $?
fx-config-read
readonly BINARIES_JSON="$FUCHSIA_BUILD_DIR/binaries.json"
readonly LLVM_OBJDUMP="$PREBUILT_CLANG_DIR/bin/llvm-objdump"
readonly GNU_OBJDUMP="$PREBUILT_BINUTILS_DIR/bin/objdump"
DEMANGLE=true
USE_LLVM=false
PATH_OBJDUMP=""
OBJDUMP_ARGS=(-d)
while getopts lSrLnP: OPT; do
case $OPT in
[lSr]) OBJDUMP_ARGS+=(-$OPT) ;;
L) USE_LLVM=true ;;
n) DEMANGLE=false ;;
P) PATH_OBJDUMP=$OPTARG ;;
esac
done
shift $((OPTIND-1))
if $DEMANGLE; then
OBJDUMP_ARGS+=(--demangle)
fi
if [[ $# -eq 0 ]]; then
fx-command-help
exit 1
fi
if [[ ! -z "$PATH_OBJDUMP" ]] ; then
readonly OBJDUMP="$PATH_OBJDUMP"
elif $USE_LLVM; then
readonly OBJDUMP="$LLVM_OBJDUMP"
else
readonly OBJDUMP="$GNU_OBJDUMP"
fi
run_jq() {
fx-command-run jq --raw-output "$@"
}
run_direct_filter() {
run_jq "$1" "$BINARIES_JSON"
}
normalize_build_ids() {
local query='
.[] | select(.elf_build_id) | "\(.elf_build_id) \(.cpu) \(.debug) \(.label)"'
run_jq "$query" "$BINARIES_JSON" | normalize_build_ids_filter
}
normalize_build_ids_filter() {
echo '['
local comma=
while read id cpu debug label; do
echo "$comma{\
\"build_id\": \"$(<"$FUCHSIA_BUILD_DIR/$id")\",\
\"cpu\": \"$cpu\",\
\"debug\": \"$debug\",\
\"label\": \"$label\"\
}"
comma=','
done
echo ']'
}
run_buildid_filter() {
normalize_build_ids | run_jq "$1"
}
is_hex() {
local str="$1"
if [[ -z "$str" ]]; then
return 0
fi
while [[ -n "$str" ]]; do
case "${str:0:1}" in
[0-9a-f]) ;;
*) return 1 ;;
esac
str="${str:1}"
done
return 0
}
RUN_FILTER=run_direct_filter
for BINARY in "$@"; do
if is_hex "$BINARY"; then
RUN_FILTER=run_buildid_filter
break
fi
done
FILTER=".[] | select(false"
for BINARY in "$@"; do
if is_hex "$BINARY"; then
FILTER+=" or (.build_id == \"$BINARY\")"
else
DEBUG_RE="(^|/)$BINARY([.]debug)?\$"
LABEL_RE=":$BINARY[(]"
FILTER+=" or (.debug | test(\"$DEBUG_RE\")) or (.label | test(\"$LABEL_RE\"))"
fi
done
FILTER+=') | "\(.debug) \(.label)"'
PATHS=($($RUN_FILTER "$FILTER"))
if (( ${#PATHS[@]} == 0 )); then
fx-error "No binaries matched any of: $*"
exit 1
fi
disassemble() {
local BINARY_PATH="$1" BINARY_LABEL="$2"
(cd "$FUCHSIA_BUILD_DIR" && "$OBJDUMP" "${OBJDUMP_ARGS[@]}" "$BINARY_PATH" > "${BINARY_PATH}.lst")
fx-info Wrote "${BINARY_PATH}.lst" for "$BINARY_LABEL"
}
i=0
while (( i < ${#PATHS[@]} )); do
disassemble "${PATHS[$i]}" "${PATHS[$((i+1))]}"
((i+=2))
done