diff --git a/projects/hip/bin/roc-obj b/projects/hip/bin/roc-obj deleted file mode 100755 index 8f93b611a9..0000000000 --- a/projects/hip/bin/roc-obj +++ /dev/null @@ -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 "$@" diff --git a/projects/hip/bin/roc-obj-extract b/projects/hip/bin/roc-obj-extract deleted file mode 100755 index 36812b5d62..0000000000 --- a/projects/hip/bin/roc-obj-extract +++ /dev/null @@ -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("-[pid]-offset-size.co\n\n"); - print("Options:\n"); - print(" -o \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, 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); diff --git a/projects/hip/bin/roc-obj-ls b/projects/hip/bin/roc-obj-ls deleted file mode 100755 index a5d6819b40..0000000000 --- a/projects/hip/bin/roc-obj-ls +++ /dev/null @@ -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);