fab70a41ed
This reverts commit 3d15f9cbda.
Reason for revert: SWDEV-368704
Change-Id: I8c38b4f40285f90f7d99145b970c2a14d051d5bb
266 行
9.8 KiB
Bash
実行ファイル
266 行
9.8 KiB
Bash
実行ファイル
#!/bin/bash
|
|
|
|
#| Usage: roc-obj [-h] [-t REGEXP] [-o OUTDIR] [-I REPLACE-STRING|-i] [-d]
|
|
#| EXECUTABLE... [: [SUFFIX COMMAND [ARGS...] ;]...]
|
|
#|
|
|
#| Wrapper for roc-obj-ls and roc-obj-extract which extracts code objects
|
|
#| embedded in each EXECUTABLE and optionally applies COMMANDs to them.
|
|
#|
|
|
#| If the POSIX extended regular expression REGEXP is specified, only embedded
|
|
#| code objects whose Target ID matches REGEXP are extracted; otherwise all
|
|
#| code objects are extracted.
|
|
#|
|
|
#| If the directory path OUTDIR is specified, it is created if it does not
|
|
#| already exist, and the code objects are extracted into it; otherwise they
|
|
#| are extracted into the current working directory.
|
|
#|
|
|
#| The extracted files are named by appending a ":" followed by the Target ID
|
|
#| of the extracted code object to the input filename EXECUTABLE they were
|
|
#| extracted from.
|
|
#|
|
|
#| If the list of EXECUTABLE arguments is terminated with ":" then after all
|
|
#| selected files are successfully extracted, zero or more additional embedded
|
|
#| command-lines, separated by ";", are read from the command-line starting
|
|
#| after the ":". These must specify a SUFFIX used to name the output of the
|
|
#| corresponding COMMAND, along with the COMMAND name and any ARGS to it.
|
|
#|
|
|
#| Then each COMMAND is executed, as if by a POSIX "execvp" function, once for
|
|
#| each embedded code object that was created in OUTDIR. (Note: Typically this
|
|
#| means the user must ensure the commands are present in at least one
|
|
#| directory of the "PATH" environment variable.) For each execution of
|
|
#| COMMAND:
|
|
#|
|
|
#| If REPLACE-STRING is specified, all instances of REPLACE-STRING in ARGS are
|
|
#| replaced with the file path of the extracted code object before executing
|
|
#| COMMAND.
|
|
#|
|
|
#| The standard input is redirected from the extracted code object.
|
|
#|
|
|
#| If SUFFIX is "-" the standard output is not redirected. If SUFFIX is "!" the
|
|
#| standard output is redirected to /dev/null. Otherwise, the standard output
|
|
#| is redirected to files named by the file path of the extracted code object
|
|
#| with SUFFIX appended.
|
|
#|
|
|
#| Note: The executables roc-obj-ls, roc-obj-extract, and llvm-objdump (in the
|
|
#| case of disassembly requested using the -d flag) are searched for in a
|
|
#| unique way. A series of directories are searched, some conditionally, until
|
|
#| a suitable executable is found. If all directories are searched without
|
|
#| finding the executable, an error occurs. The first directory searched is the
|
|
#| one containing the hard-link to the roc-obj being executed, known as the
|
|
#| "base directory". Next, if the environment variable HIP_CLANG_PATH is set,
|
|
#| it is searched; otherwise, the base directory path is appended with
|
|
#| "../../llvm/bin" and it is searched. Finally, the PATH is searched as if by
|
|
#| a POSIX "execvp" function.
|
|
#|
|
|
#| Option Descriptions:
|
|
#| -h, --help print this help text and exit
|
|
#| -t, --target-id only extract code objects from EXECUTABLE whose Target ID
|
|
#| matches the POSIX extended regular expression REGEXP
|
|
#| -o, --outdir set the output directory, which is created if it
|
|
#| does not exist
|
|
#| -I, --replace-string replace all occurrences of the literal string
|
|
#| REPLACE-STRING in ARGS with the input filename
|
|
#| -i, --replace equivalent to -I{}
|
|
#| -d, --disassemble diassemble extracted code objects; equivalent to
|
|
#| : .s llvm-objdump -d - ;
|
|
#|
|
|
#| Example Usage:
|
|
#|
|
|
#| Extract all code objects embedded in a.so:
|
|
#| $ roc-obj a.so
|
|
#|
|
|
#| Extract all code objects embedded in a.so, b.so, and c.so:
|
|
#| $ roc-obj a.so b.so c.so
|
|
#|
|
|
#| Extract all code objects embedded in a.so with "gfx9" in their Target ID:
|
|
#| $ roc-obj -t gfx9 a.so
|
|
#|
|
|
#| Extract all code objects embedded in a.so into output/ (creating it if needed):
|
|
#| $ roc-obj -o output/ a.so
|
|
#|
|
|
#| Extract all code objects embedded in a.so with "gfx9" in their Target ID
|
|
#| into output/ (creating it if needed):
|
|
#| $ roc-obj -t gfx9 -o output/ a.so
|
|
#|
|
|
#| Extract all code objects embedded in a.so, and then disassemble each of them
|
|
#| to files ending with .s:
|
|
#| $ roc-obj -d a.so
|
|
#|
|
|
#| Extract all code objects embedded in a.so, and count the number of bytes in
|
|
#| each, writing the results to files ending with .count:
|
|
#| $ roc-obj a.so : .count wc -c
|
|
#|
|
|
#| Extract all code objects embedded in a.so, and inspect their ELF headers
|
|
#| using llvm-readelf (which will not read from standard input), writing to
|
|
#| files ending with .hdr:
|
|
#| $ roc-obj -I'{}' a.so : .hdr llvm-readelf -h '{}'
|
|
#|
|
|
#| Extract all code objects embedded in a.so, and then extract each of their
|
|
#| .text sections using llvm-objcopy (which won't read from standard input
|
|
#| or write to standard output):
|
|
#| $ roc-obj -I'{}' a.so : ! llvm-objcopy -O binary :only-section=.text '{}' '{}.text'
|
|
#|
|
|
#| Extract all code objects embedded in a.so, b.so, and c.so with target
|
|
#| feature xnack disabled into directory out/. Then, for each:
|
|
#| Write the size in bytes into a file ending with .count, and
|
|
#| Write a textual description of the ELF headers to a file ending with .hdr, and
|
|
#| Extract the .text section to a file ending with .text
|
|
#| $ roc-obj -I'{}' -t xnack- -o out/ a.so b.so c.so : \
|
|
#| .count wc -c \;
|
|
#| .hdr llvm-readelf -h '{}' \;
|
|
#| ! llvm-objcopy -O binary --only-section=.text '{}' '{}.text'
|
|
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
sed -n 's/^#| \?\(.*\)$/\1/p' "$0"
|
|
}
|
|
|
|
usage_then_exit() {
|
|
local -r status="$1"; shift
|
|
usage >&$(( status ? 2 : 1 ))
|
|
exit "$status"
|
|
}
|
|
|
|
fail() {
|
|
printf "error: %s\n" "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
# Account for the fact that we do not necessarily put ROCm tools in the PATH,
|
|
# nor do we have a single, unified ROCm "bin/" directory.
|
|
#
|
|
# Note that this is only used for roc-obj-ls, roc-obj-extract, and "shortcut"
|
|
# options like -d, and the user can still use any copy of llvm-* by explicitly
|
|
# invoking it with a full path, e.g. : /path/to/llvm-* ... ;
|
|
find_rocm_executable_or_fail() {
|
|
local -r command="$1"; shift
|
|
local file
|
|
local searched=()
|
|
for dir in "$BASE_DIR" "${HIP_CLANG_PATH:-"$BASE_DIR/../../llvm/bin"}"; do
|
|
file="$dir/$command"
|
|
if [[ -x $file ]]; then
|
|
printf "%s" "$file"
|
|
return
|
|
else
|
|
searched+=("$dir")
|
|
fi
|
|
done
|
|
if hash "$command" 2>/dev/null; then
|
|
printf "%s" "$command"
|
|
else
|
|
fail could not find "$command" in "${searched[*]}" or PATH
|
|
fi
|
|
}
|
|
|
|
# Extract the embedded code objects of the executable file given as the first
|
|
# argument into OPT_OUTDIR, filtering them via OPT_TARGET_ID.
|
|
#
|
|
# Deletes any resulting files which are empty, and prints the paths of the
|
|
# remaining files.
|
|
extract() {
|
|
local -r executable="$1"; shift
|
|
local prefix
|
|
prefix="$(basename -- "$executable")"
|
|
# We want the shell to split the result of roc-obj-ls on whitespace, as
|
|
# neither the Target ID nor the URI can have embedded spaces.
|
|
# shellcheck disable=SC2046
|
|
set -- $("$ROC_OBJ_LS" -- "$executable" | awk "\$2~/$OPT_TARGET_ID/")
|
|
while (( $# )); do
|
|
local output="$prefix:$1"; shift
|
|
output="$output.$1"; shift
|
|
local uri="$1"; shift
|
|
[[ -n $OPT_OUTDIR ]] && output="$OPT_OUTDIR/$output"
|
|
"$ROC_OBJ_EXTRACT" -o - -- "$uri" >"$output"
|
|
if [[ -s $output ]]; then
|
|
printf '%s\n' "$output"
|
|
else
|
|
rm "$output"
|
|
fi
|
|
done
|
|
(( $# )) && fail expected even number of fields from roc-obj-ls
|
|
}
|
|
|
|
# Run a command over a list of inputs, naming output files with the supplied
|
|
# suffix and applying OPT_REPLACE_STRING if needed.
|
|
#
|
|
# Arguments are of the form:
|
|
# $suffix $command $args... ; $inputs
|
|
run_command() {
|
|
local -r suffix="$1"; shift
|
|
local -r command="$1"; shift
|
|
local args=()
|
|
while (( $# )); do
|
|
local arg="$1"; shift
|
|
[[ $arg == ';' ]] && break
|
|
args+=("$arg")
|
|
done
|
|
local inputs=("$@")
|
|
for input in "${inputs[@]}"; do
|
|
case "$suffix" in
|
|
'-') output=/dev/stdout;;
|
|
'!') output=/dev/null;;
|
|
*) output="$input$suffix";;
|
|
esac
|
|
"$command" "${args[@]//$OPT_REPLACE_STRING/$input}" <"$input" >"$output"
|
|
done
|
|
}
|
|
|
|
main() {
|
|
[[ -n $OPT_OUTDIR ]] && mkdir -p "$OPT_OUTDIR"
|
|
local inputs=()
|
|
while (( $# )); do
|
|
local executable="$1"; shift
|
|
[[ $executable == : ]] && break
|
|
# Append the file paths extracted from $executable to $inputs
|
|
readarray -t -O "${#inputs[@]}" inputs < <(extract "$executable")
|
|
done
|
|
(( ${#inputs[@]} )) || fail no executables specified
|
|
while (( $# )); do
|
|
local suffix="$1"; shift
|
|
local command="$1"; shift
|
|
local args=()
|
|
while (( $# )); do
|
|
local arg="$1"; shift
|
|
[[ $arg == \; ]] && break
|
|
args+=("$arg")
|
|
done
|
|
run_command "$suffix" "$command" "${args[@]}" \; "${inputs[@]}"
|
|
done
|
|
(( OPT_DISASSEMBLE )) && run_command .s "$OBJDUMP" -d - \; "${inputs[@]}"
|
|
}
|
|
|
|
OPT_TARGET_ID=''
|
|
OPT_OUTDIR=''
|
|
OPT_REPLACE_STRING=''
|
|
OPT_DISASSEMBLE=0
|
|
! getopt -T || fail util-linux enhanced getopt required
|
|
getopt="$(getopt -o +ht:o:I:id \
|
|
--long help,target-id:,outdir:,replace:,replace-default,disassemble \
|
|
-n roc-obj -- "$@")"
|
|
eval set -- "$getopt"
|
|
unset getopt
|
|
while true; do
|
|
case "$1" in
|
|
-h | --help) usage_then_exit 0;;
|
|
-t | --target-id) OPT_TARGET_ID="${2//\//\\\/}"; shift 2;;
|
|
-o | --outdir) OPT_OUTDIR="$2"; shift 2;;
|
|
-I | --replace-string) OPT_REPLACE_STRING="$2"; shift 2;;
|
|
-i | --replace) OPT_REPLACE_STRING='{}'; shift;;
|
|
-d | --disassemble) OPT_DISASSEMBLE=1; shift;;
|
|
--) shift; break;;
|
|
*) usage_then_exit 1;;
|
|
esac
|
|
done
|
|
readonly -- OPT_TARGET_ID OPT_OUTDIR OPT_REPLACE_STRING OPT_DISASSEMBLE
|
|
|
|
# We expect to be installed as ROCM_PATH/hip/bin/roc-obj, which means BASE_DIR
|
|
# is ROCM_PATH/hip/bin.
|
|
BASE_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
|
(( OPT_DISASSEMBLE )) && OBJDUMP="$(find_rocm_executable_or_fail llvm-objdump)"
|
|
ROC_OBJ_LS="$(find_rocm_executable_or_fail roc-obj-ls)"
|
|
ROC_OBJ_EXTRACT="$(find_rocm_executable_or_fail roc-obj-extract)"
|
|
readonly -- BASE_DIR OBJDUMP ROC_OBJ_LS ROC_OBJ_EXTRACT
|
|
|
|
main "$@"
|