SWDEV-294828 - Move roc-obj binaries from hip to hipamd
Change-Id: I2a234c46d8516737b7153594e7f978ce3247d6e8
[ROCm/hip commit: a797475e35]
This commit is contained in:
@@ -1,264 +0,0 @@
|
||||
#!/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 -v -- "$executable" | awk "NR>2 && \$1~/$OPT_TARGET_ID/")
|
||||
while (( $# )); do
|
||||
local output="$prefix:$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 +hg: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.
|
||||
readonly BASE_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
|
||||
(( OPT_DISASSEMBLE )) \
|
||||
&& readonly OBJDUMP="$(find_rocm_executable_or_fail llvm-objdump)"
|
||||
readonly ROC_OBJ_LS="$(find_rocm_executable_or_fail roc-obj-ls)"
|
||||
readonly ROC_OBJ_EXTRACT="$(find_rocm_executable_or_fail roc-obj-extract)"
|
||||
|
||||
main "$@"
|
||||
@@ -1,229 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
use strict;
|
||||
use File::Copy;
|
||||
use File::Spec;
|
||||
use File::Basename;
|
||||
use File::Which;
|
||||
use Cwd 'realpath';
|
||||
use Getopt::Std;
|
||||
use List::Util qw(max);
|
||||
use URI::Encode;
|
||||
|
||||
my $extract_range_specifier;
|
||||
my $extract_pid;
|
||||
my $extract_file;
|
||||
my $output_file;
|
||||
my $output_path;
|
||||
my $extract_offset;
|
||||
my $extract_size;
|
||||
my $pid_running;
|
||||
my $verbose=0;
|
||||
my $error=0;
|
||||
my $output_to_stdout=0;
|
||||
|
||||
sub usage {
|
||||
print("Usage: $0 [-o|v|h] URI... \n");
|
||||
print(" URIs can be read from STDIN, one per line.\n");
|
||||
print(" From the URIs specified, extracts code objects into files named: ");
|
||||
print("<executable_name>-[pid<number>]-offset<number>-size<number>.co\n\n");
|
||||
print("Options:\n");
|
||||
print(" -o <path> \tPath for output. If \"-\" specified, code object is printed to STDOUT.\n");
|
||||
print(" -v \tVerbose output to STDOUT (includes Entry ID).\n");
|
||||
print(" -h \tShow this help message.\n");
|
||||
print("\nURI syntax:\n");
|
||||
print("\tcode_object_uri ::== file_uri | memory_uri\n");
|
||||
print("\tfile_uri ::== \"file://\" extract_file [ range_specifier ]\n");
|
||||
print("\tmemory_uri ::== \"memory://\" process_id range_specifier\n");
|
||||
print("\trange_specifier ::== [ \"#\" | \"?\" ] \"offset=\" number \"&\" \"size=\" number\n");
|
||||
print("\textract_file ::== URI_ENCODED_OS_FILE_PATH\n");
|
||||
print("\tprocess_id ::== DECIMAL_NUMBER\n");
|
||||
print("\tnumber ::== HEX_NUMBER \| DECIMAL_NUMBER \| OCTAL_NUMBER\n\n");
|
||||
print("\tExample: file://dir1/dir2/hello_world#offset=133&size=14472 \n");
|
||||
print("\t memory://1234#offset=0x20000&size=3000\n\n");
|
||||
|
||||
exit($error);
|
||||
}
|
||||
|
||||
# Process options
|
||||
my %options=();
|
||||
getopts('vho:', \%options);
|
||||
|
||||
if (defined $options{h}) {
|
||||
usage();
|
||||
}
|
||||
|
||||
if (defined $options{v}) {
|
||||
$verbose = 1;
|
||||
}
|
||||
|
||||
if (defined $options{o}) {
|
||||
$output_path = $options{o};
|
||||
if ($output_path eq "-") {
|
||||
$output_to_stdout=1;
|
||||
} else {
|
||||
(-d $output_path) || die("Error: Path \'$output_path\' cannot be found.\n");
|
||||
}
|
||||
}
|
||||
|
||||
# push STDIN to ARGV array.
|
||||
push @ARGV, <STDIN> unless -t STDIN;
|
||||
|
||||
# error check: enough arguments presented.
|
||||
if ($#ARGV < 0) {
|
||||
print(STDERR "Error: No arguments.\n"); $error++;
|
||||
usage();
|
||||
}
|
||||
|
||||
# error check: command dd is available.
|
||||
my $dd_cmd = which("dd");
|
||||
(-f $dd_cmd) || die("Error: Can't find dd command\n");
|
||||
|
||||
foreach my $uri_str(@ARGV) {
|
||||
chomp $uri_str;
|
||||
|
||||
# we expect the URI to follow this BNF syntax:
|
||||
#
|
||||
# code_object_uri ::== file_uri | memory_uri
|
||||
# file_uri ::== "file://" extract_file [ range_specifier ]
|
||||
# memory_uri ::== "memory://" process_id range_specifier
|
||||
# range_specifier ::== [ "#" | "?" ] "offset=" number "&" "size=" number
|
||||
# extract_file ::== URI_ENCODED_OS_FILE_PATH
|
||||
# process_id ::== DECIMAL_NUMBER
|
||||
# number ::== HEX_NUMBER | DECIMAL_NUMBER | OCTAL_NUMBER
|
||||
|
||||
# Example: file://dir1/dir2/hello_world#offset=133&size=14472
|
||||
# memory://1234#offset=0x20000&size=3000
|
||||
|
||||
my ($uri_protocol, $specs) = split(/:\/\//,$uri_str);
|
||||
my $obj_uri_encode = URI::Encode->new();
|
||||
my $decoded_extract_file;
|
||||
|
||||
if (lc($uri_protocol) eq "file") {
|
||||
# expect file path
|
||||
($extract_file, $extract_range_specifier) = split(/[#,?]/,$specs);
|
||||
|
||||
# decode the file name. URIs may have file/path names with non-alphanumeric characters, which will be encoded with %. We need to decode these.
|
||||
$decoded_extract_file = $obj_uri_encode->decode($extract_file);
|
||||
|
||||
# verify file exists:
|
||||
if (! -e $decoded_extract_file) {
|
||||
print(STDERR "Error: can't find file: $decoded_extract_file\n"); $error++;
|
||||
next;
|
||||
}
|
||||
|
||||
# use the output_path is specified, otherwise use current working dir.
|
||||
if ($output_path ne "") {
|
||||
$output_file = File::Spec->catfile($output_path, basename($decoded_extract_file));
|
||||
} else {
|
||||
$output_file = basename($decoded_extract_file);
|
||||
}
|
||||
|
||||
} elsif ( lc($uri_protocol) eq "memory") {
|
||||
# expect memory specifier
|
||||
($extract_pid, $extract_range_specifier) = split(/[#,?]/,$specs);
|
||||
|
||||
# verify pid is currently running
|
||||
$pid_running = kill 0, $extract_pid;
|
||||
if (! $pid_running) {
|
||||
print(STDERR "Error: PID: $extract_pid is NOT running\n"); $error++;
|
||||
next;
|
||||
}
|
||||
|
||||
# get pid filename:
|
||||
$extract_file = "/proc/$extract_pid/mem";
|
||||
|
||||
# verify file exists:
|
||||
if (! -e $extract_file) {
|
||||
print(STDERR "Error: can't find file: $extract_file\n"); $error++;
|
||||
next;
|
||||
}
|
||||
|
||||
# for extracting from a pid, make the output file in the current dir/path with the pid value as a name.
|
||||
$output_file = "pid${extract_pid}";
|
||||
|
||||
# need to set $decoded_extract_file, because later we use this for other checks.
|
||||
$decoded_extract_file = $extract_file;
|
||||
|
||||
} else {
|
||||
# error, unrecognized Code Object URI
|
||||
print(STDERR "Error: \'$uri_protocol\' is not recognized as a supported code object URI.\n"); $error++;
|
||||
next;
|
||||
}
|
||||
|
||||
# it is valid to not give a range specifier in a URI, in which case the entire code object will be extracted.
|
||||
if ($extract_range_specifier ne "") {
|
||||
($extract_offset, $extract_size) = split(/[&]/,$extract_range_specifier);
|
||||
(undef, $extract_offset) = split(/=/,$extract_offset);
|
||||
(undef, $extract_size) = split(/=/,$extract_size);
|
||||
} else {
|
||||
# Error if URI is a memory request, and we have no range_specifier.
|
||||
if ($pid_running) {
|
||||
print(STDERR "Error: must specify a Range Specifier (offset and size) for a memory URI: $uri_str\n"); $error++;
|
||||
next;
|
||||
}
|
||||
|
||||
$extract_offset = 0;
|
||||
$extract_size = -s $decoded_extract_file;
|
||||
}
|
||||
|
||||
# We should have at least a valid size to extract; ignore cases with size=0.
|
||||
if ($extract_size != 0) {
|
||||
print("Reading input file \"$extract_file\" ...\n") if ($verbose);
|
||||
|
||||
# only if this is a File URI.
|
||||
if (lc($uri_protocol) eq "file") {
|
||||
# verify that offset+size does not exceed file size:
|
||||
my $file_size = -s $decoded_extract_file;
|
||||
my $size = int($extract_offset) + int($extract_size);
|
||||
if ( $size > $file_size ) {
|
||||
print(STDERR "Error: requested offset($extract_offset) + size($extract_size) exceeds file size($file_size) for file \"$decoded_extract_file\".\n"); $error++;
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
open(INPUT_FP, "<", $decoded_extract_file) || die $!;
|
||||
binmode INPUT_FP;
|
||||
|
||||
# extract the code object
|
||||
my $co_filename;
|
||||
if (!$output_to_stdout) {
|
||||
$co_filename = "of=\'${output_file}-offset${extract_offset}-size${extract_size}.co\'";
|
||||
}
|
||||
|
||||
my $dd_cmd_str = "$dd_cmd if=\'$decoded_extract_file\' $co_filename skip=$extract_offset count=$extract_size bs=1 status=none";
|
||||
|
||||
print("DD Command: $dd_cmd_str\n") if ($verbose);
|
||||
|
||||
my $dd_ret = system($dd_cmd_str);
|
||||
if ($dd_ret != 0) {
|
||||
print(STDERR "Error: DD command ($dd_cmd_str) failed with RC: $dd_ret\n"); $error++;
|
||||
}
|
||||
|
||||
print("Extract request: file: $extract_file offset: $extract_offset size: $extract_size\n") if ($verbose);
|
||||
} else {
|
||||
print("Warning: trying to extract from $extract_file at offset=$extract_offset with size=0. Nothing to extract.\n") if ($verbose);
|
||||
}
|
||||
|
||||
} # end of for each (URI) argument
|
||||
|
||||
exit($error);
|
||||
@@ -1,156 +0,0 @@
|
||||
#!/usr/bin/perl
|
||||
# Copyright (c) 2020 - 2021 Advanced Micro Devices, Inc. All rights reserved.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
use strict;
|
||||
use File::Copy;
|
||||
use File::Spec;
|
||||
use File::Basename;
|
||||
use File::Which;
|
||||
use Cwd 'realpath';
|
||||
use Getopt::Std;
|
||||
use List::Util qw(max);
|
||||
use URI::Encode;
|
||||
|
||||
sub usage {
|
||||
print("Usage: $0 [-v|h] executable...\n");
|
||||
print("List the URIs of the code objects embedded in the specfied host executables.\n");
|
||||
print("-v \tVerbose output (includes Entry ID)\n");
|
||||
print("-h \tShow this help message\n");
|
||||
exit;
|
||||
}
|
||||
|
||||
# sub to read a qword. 1st arg is a FP, 2nd arg is ref to destination var.
|
||||
sub readq {
|
||||
my ($input_fp, $qword) = @_;
|
||||
read($input_fp, my $bytes, 8) == 8 or die("Error: Failed to read 8 bytes\n");
|
||||
${$qword} = unpack("Q<", $bytes);
|
||||
}
|
||||
|
||||
# Process options
|
||||
my %options=();
|
||||
getopts('vhd', \%options);
|
||||
|
||||
if (defined $options{h}) {
|
||||
usage();
|
||||
}
|
||||
|
||||
my $verbose = $options{v};
|
||||
my $debug = $options{d};
|
||||
|
||||
# look for objdump
|
||||
my $objdump = which("objdump");
|
||||
(-f $objdump) || die("Error: Can't find objdump command\n");
|
||||
|
||||
# for each argument (which should be an executable):
|
||||
foreach my $executable_file(@ARGV) {
|
||||
|
||||
# debug message
|
||||
print("Reading input file \"$executable_file\" ...\n") if ($debug);
|
||||
|
||||
# verify/open file specified.
|
||||
open (INPUT_FP, "<", $executable_file) || die("Error: failed to open file: $executable_file\n");
|
||||
binmode INPUT_FP;
|
||||
|
||||
# kernel section information
|
||||
my $escaped_name=quotemeta($executable_file);
|
||||
my $bundle_section_name = ".hip_fatbin";
|
||||
my $bundle_section_size = hex(`$objdump -h $escaped_name | grep $bundle_section_name | awk '{print \$3}'`);
|
||||
my $bundle_section_offset = hex(`$objdump -h $escaped_name | grep $bundle_section_name | awk '{print \$6}'`);
|
||||
|
||||
$bundle_section_size or die("Error: No kernel section found\n");
|
||||
|
||||
my $bundle_section_end = $bundle_section_offset + $bundle_section_size;
|
||||
|
||||
if ($debug) {
|
||||
print "Code Objects Bundle section size: $bundle_section_size\n";
|
||||
print "Code Objects Bundle section offset: $bundle_section_offset\n";
|
||||
print "Code Objects Bundle section end: $bundle_section_end\n";
|
||||
}
|
||||
|
||||
my $current_bundle_offset = $bundle_section_offset;
|
||||
print "Current Bundle offset: $current_bundle_offset\n" if ($debug);
|
||||
|
||||
# move fp to current_bundle_offset.
|
||||
seek(INPUT_FP, $current_bundle_offset, 0);
|
||||
|
||||
# skip OFFLOAD_BUNDLER_MAGIC_STR
|
||||
my $magic_str;
|
||||
my $read_bytes = read(INPUT_FP, $magic_str, 24);
|
||||
if (($read_bytes != 24) || ($magic_str ne "__CLANG_OFFLOAD_BUNDLE__")) {
|
||||
print(STDERR "Error: Offload bundle magic string not detected\n") if ($debug);
|
||||
last;
|
||||
}
|
||||
|
||||
# read number of bundle entries, which are code objects.
|
||||
my $num_codeobjects;
|
||||
readq(\*INPUT_FP,\$num_codeobjects);
|
||||
# $num_codeobjects = unpack("Q<", $num_codeobjects);
|
||||
|
||||
# Listing
|
||||
print "Bundle of $num_codeobjects HIP Code Objects:\n" if ($verbose);
|
||||
|
||||
# strings for creating new files
|
||||
my $file_co_number = sprintf("%03d", $num_codeobjects);
|
||||
my $filename_prefix = "${executable_file}-${file_co_number}";
|
||||
|
||||
print("Entry ID:\t\t\tURI:\n") if ($verbose);
|
||||
|
||||
# for each Bundle entry (code object) ....
|
||||
for (my $iter = 0; $iter < $num_codeobjects; $iter++) {
|
||||
|
||||
# read bundle entry (code object) offset
|
||||
my $entry_offset;
|
||||
my $abs_offset;
|
||||
readq(*INPUT_FP,\$entry_offset);
|
||||
print("entry_offset: $entry_offset\n") if $debug;
|
||||
|
||||
# read bundle entry (code object) size
|
||||
my $entry_size;
|
||||
readq(*INPUT_FP,\$entry_size);
|
||||
print("entry_size: $entry_size\n") if $debug;
|
||||
|
||||
# read triple size
|
||||
my $triple_size;
|
||||
readq(*INPUT_FP,\$triple_size);
|
||||
print("triple_size: $triple_size\n") if $debug;
|
||||
|
||||
# read triple string
|
||||
my $triple;
|
||||
my $read_bytes = read(INPUT_FP, $triple, $triple_size);
|
||||
$read_bytes == $triple_size or die("Error: Fail to parse triple\n");
|
||||
print("triple: $triple\n") if $debug;
|
||||
|
||||
# because the bundle entry's offset is relative to the beginning of the bundled code object section.
|
||||
$abs_offset = int($entry_offset) + $bundle_section_offset;
|
||||
|
||||
my $obj_uri_encode = URI::Encode->new();
|
||||
my $encoded_executable_file = $obj_uri_encode->encode($executable_file);
|
||||
|
||||
if ($verbose) {
|
||||
print(STDOUT "$triple\tfile:\/\/$encoded_executable_file#offset=$abs_offset\&size=$entry_size\n");
|
||||
} else {
|
||||
print(STDOUT "file:\/\/$encoded_executable_file#offset=$abs_offset\&size=$entry_size\n");
|
||||
}
|
||||
|
||||
} # End of for each Bundle entry (code object) ...
|
||||
} # End of for each command line argument
|
||||
|
||||
exit(0);
|
||||
Fai riferimento in un nuovo problema
Block a user