ProxSpace/msys2/usr/bin/dep-search

230 lines
No EOL
6.7 KiB
Bash

#!/usr/bin/env bash
#
# dep-search - utility for searching library dependencies
# of Windows executables and shared libraries.
#
# The BSD 3-Clause License. http://www.opensource.org/licenses/BSD-3-Clause
#
# This file is part of 'MSYS2' project.
# Copyright (c) 2014 by Alexpux (alexpux doggy gmail dotty com)
# All rights reserved.
#
# Project: MSYS2 ( http://sourceforge.net/projects/msys2/ )
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the distribution.
# - Neither the name of the 'MinGW-W64' nor the names of its contributors may
# be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# **************************************************************************
# dep-search uses quite a few external programs during its execution. You
# need to have at least the following installed for dep-search to function:
# binutils, grep, sed
#
declare -r depsearch_name='dep-search'
declare -r depsearch_version='0.1'
_search_dir=$(pwd)
_search_file=
_search_pattern=
_search_mode=all
_prog_output=plain
_run_mode=dir
_verbose=0
export LC_ALL=C
### SUBROUTINES ###
plain() {
local mesg=$1; shift
printf "${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
print_msg0() {
local mesg=$1; shift
printf "${YELLOW}=> ${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
print_msg1() {
local mesg=$1; shift
printf "${GREEN}==> ${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
print_msg2() {
local mesg=$1; shift
printf "${BLUE} ->${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
print_error() {
local mesg=$1; shift
printf "${RED}==> ERROR:${ALL_OFF}${BOLD} ${mesg}${ALL_OFF}\n" "$@" >&2
}
die() {
# $1 - message to die
printf "$1"
exit 1
}
usage() {
printf "$depsearch_name (MSYS2) %s\n" "$depsearch_version"
echo
printf -- "Usage: %s [options]\n" "$0"
echo
printf -- "Options:\n"
printf -- " --directory=<dir> Search dependencies in specified directory\n"
printf -- " --file=<filename> Search dependencies for specified executable\n"
printf -- " --library=<library_pattern> Pattern of library that need to be resolved as dependency\n"
printf -- " --output=[list|plain] Output search result for human(plain) or as list of executables.\n"
printf -- " --verbose Output more information.\n"
echo
}
version() {
printf "$depsearch_name (MSYS2) %s\n" "$depsearch_version"
printf -- "Copyright (c) 2014 by Alexpux (alexpux doggy gmail dotty com).\n"
}
process_binary() {
# $1 - windows PE file
# $2 - search pattern
# process all libraries needed by the binary
if [[ -n $2 ]]; then
local _lower_pattern=$(echo $2 | tr 'A-Z' 'a-z')
fi
local _sofile=
for _sofile in $(LC_ALL=C objdump -x "$1" 2>/dev/null | sed -nr 's/.*DLL Name: (.*).*/\1/p')
do
if [[ -n $2 ]]; then
local _lower_sofile=$(echo $_sofile | tr 'A-Z' 'a-z')
if [ "$(echo $_lower_sofile | grep -Eio $_lower_pattern)" = "$_lower_pattern" ]; then
if [[ $_verbose = 1 ]]; then
print_msg2 "$1: $_sofile"
else
print_msg2 "$(basename $1): $_sofile"
fi
fi
else
print_msg2 "$_sofile"
fi
done
}
process_directory() {
# $1 - derectory to search
# $2 - search pattern
local _file_list=$(find "$1" -type f -name "*.dll" -o -name "*.exe" -o -name "*.so" -o -name "*.pyd")
local _it=
if [[ ${#_file_list[@]} = 0 ]]; then
print_msg1 "There are no executables or dll's in $1."
else
for _it in ${_file_list[@]}; do
if [[ $_verbose = 1 ]]; then
print_msg1 "Processing $_it"
fi
process_binary "$_it" "$2"
done
fi
}
# check if messages are to be printed using color
unset ALL_OFF BOLD BLUE GREEN RED YELLOW
if [[ -t 2 && ! $USE_COLOR = "n" ]]; then
# prefer terminal safe colored and bold text when tput is supported
if /usr/bin/tput setaf 0 &>/dev/null; then
ALL_OFF="$(/usr/bin/tput sgr0)"
BOLD="$(/usr/bin/tput bold)"
BLUE="${BOLD}$(/usr/bin/tput setaf 4)"
GREEN="${BOLD}$(/usr/bin/tput setaf 2)"
RED="${BOLD}$(/usr/bin/tput setaf 1)"
YELLOW="${BOLD}$(/usr/bin/tput setaf 3)"
else
ALL_OFF="\e[1;0m"
BOLD="\e[1;1m"
BLUE="${BOLD}\e[1;34m"
GREEN="${BOLD}\e[1;32m"
RED="${BOLD}\e[1;31m"
YELLOW="${BOLD}\e[1;33m"
fi
fi
readonly ALL_OFF BOLD BLUE GREEN RED YELLOW
if [[ $1 = -@(h|-help) ]]; then
usage
exit 0
elif [[ $1 = -@(V|-version) ]]; then
version
exit 0
fi
# parse arguments
while [[ $# > 0 ]]; do
case $1 in
--directory=*)
_search_dir=${1/--directory=/}
_run_mode=dir
if [[ ! -d $_search_dir ]]; then
print_error "Search directory doesn't exists"
exit 1
fi
;;
--file=*)
_search_file=${1/--file=/}
_run_mode=file
if [[ ! -f $_search_file ]]; then
print_error "File $_search_file doesn't exists"
exit 1
fi
;;
--library=*)
_search_pattern=${1/--library=/}
_search_mode=single
;;
--output=*)
_prog_output=${1/--output=/}
;;
--verbose)
_verbose=1
;;
--help) usage ;;
*)
die "bad command line: \"$1\". terminate."
;;
esac
shift
done
_ext_msg=
if [[ -n $_search_pattern ]]; then
_ext_msg="on $_search_pattern"
fi
if [[ "$_run_mode" = "file" ]]; then
print_msg0 "Scanning file %s for dependencies %s" "$_search_file" "$_ext_msg"
process_binary "$_search_file" "$_search_pattern"
else
print_msg0 "Scanning directory %s for dependencies %s" "$_search_dir" "$_ext_msg"
process_directory "$_search_dir" "$_search_pattern"
fi
exit 0