#!/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= Search dependencies in specified directory\n" printf -- " --file= Search dependencies for specified executable\n" printf -- " --library= 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