From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) by finch.gentoo.org (Postfix) with ESMTP id B8DAA1387FD for ; Sun, 8 Jun 2014 16:23:50 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 53CF6E08FF; Sun, 8 Jun 2014 16:23:49 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id D60DAE08FF for ; Sun, 8 Jun 2014 16:23:48 +0000 (UTC) Received: from spoonbill.gentoo.org (spoonbill.gentoo.org [81.93.255.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id B2D8533FFBB for ; Sun, 8 Jun 2014 16:23:47 +0000 (UTC) Received: from localhost.localdomain (localhost [127.0.0.1]) by spoonbill.gentoo.org (Postfix) with ESMTP id 75852181A9 for ; Sun, 8 Jun 2014 16:23:45 +0000 (UTC) From: "Michael Palimaka" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Michael Palimaka" Message-ID: <1402244606.29ece55c0c90b5bbe8ab21ddd6e0363ea9bd053a.kensington@gentoo> Subject: [gentoo-commits] proj/qa-scripts:master commit in: / X-VCS-Repository: proj/qa-scripts X-VCS-Files: depcheck X-VCS-Directories: / X-VCS-Committer: kensington X-VCS-Committer-Name: Michael Palimaka X-VCS-Revision: 29ece55c0c90b5bbe8ab21ddd6e0363ea9bd053a X-VCS-Branch: master Date: Sun, 8 Jun 2014 16:23:45 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Archives-Salt: 043fbf1c-a550-49de-957e-8876e27e4f35 X-Archives-Hash: 6e4d775d8e8efab4ba779eba6625bf7c commit: 29ece55c0c90b5bbe8ab21ddd6e0363ea9bd053a Author: Michael Palimaka gentoo org> AuthorDate: Sun Jun 8 16:23:26 2014 +0000 Commit: Michael Palimaka gentoo org> CommitDate: Sun Jun 8 16:23:26 2014 +0000 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/qa-scripts.git;a=commit;h=29ece55c depcheck: add script for checking binary runtime dependencies. --- depcheck | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) diff --git a/depcheck b/depcheck new file mode 100755 index 0000000..15e171e --- /dev/null +++ b/depcheck @@ -0,0 +1,258 @@ +#!/bin/bash +# +# Copyright (c) 2014 Michael Palimaka +# +# 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. +# +# A tool to report both undeclared and potentially-unused runtime dependencies. +# +# Depends on app-misc/pax-utils, app-portage/portage-utils and +# sys-apps/gentoo-functions. + +DEBUG=FALSE +IGNORE_DEPS=( "sys-libs/glibc" "sys-devel/gcc" ) +IGNORE_LINKS=( "/lib64/libgcc_s.so.1" ) +PKG_DIR="/var/db/pkg/" + +. /lib/gentoo/functions.sh + +bold() { + echo $@ + return + local bold=$(tput bold) + local normal=$(tput sgr0) + echo "${bold}${@}${normal}" +} + +debug() { + if [ $DEBUG = TRUE ]; then + # write to stderr so as not to interfere with function returns + echo "$@" 1>&2 + fi +} + +# app-foo/bar-1.2.3-r1 -> app-foo/bar +remove_atom_version() { + local atom=`qatom "${1}" | cut -d " " -f 1-2 | tr " " /` + echo $atom +} + +check_atom() { + + local errors=0 + local atom=$1 + local checked=() + local rdepends=() + + local objects=`qlist -qo ${atom}` + + if [ ! "${objects}" ]; then + einfo ${atom} does not have any objects installed, skipping... + echo + return + fi + + einfo Checking ${atom} for undeclared dependencies + eindent + + local obj + for obj in $objects + do + debug "Checking ${obj}" + + readelf -h ${obj} > /dev/null 2>&1 + + # can it have stuff linked to it? + if [ $? -ne 0 ]; then + debug "It can't have links, skipping" + continue + fi + + local elf=`scanelf --format "#f%n" --nobanner --use-ldpath ${obj} 2>&1` + local links=`echo ${elf} | tr "," " "` + + # get a list of everything that it's linked to + local link + for link in $links + do + local ignore + for ignore in "${IGNORE_LINKS[@]}"; do + if [ "${ignore}" = "${link}" ]; then + debug "Ignoring ${link} due to blacklist" + continue 2 + fi + done + + # only check a library once per atom for performance reasons + local check + for check in "${checked[@]}"; do + if [ "${check}" = "${link}" ]; then + debug "Already checked ${link} for this atom, skipping" + continue 2 + fi + done + + checked=( "${checked[@]}" "${link}" ) + + debug "Found ${link}" + + local libowner=`qfile -vqC ${link} | uniq` + + if [ ! "${libowner}" ]; then + ewarn "No package claims ${link} (${obj})" + continue + fi + + debug "Owning package for ${link} is ${libowner}" + + local libowner_pn=$(remove_atom_version ${libowner}) + local my_pn=$(remove_atom_version ${atom}) + + rdepends+=( "${libowner_pn}" ) + + if [ "${libowner_pn}" = "${my_pn}" ]; then + debug "Owning package is self, ignoring" + continue + fi + + local ignorelib + for ignorelib in "${IGNORE_DEPS[@]}" + do + if [ "${libowner_pn}" = "${ignorelib}" ]; then + debug "Ignoring objects belonging to ${ignorelib}" + continue 2 + fi + done + + debug "Checking if ${libowner_pn} is in the RDEPEND list of ${atom}" + + local isdep + isdep=`qdepends -r ${atom} | grep ${libowner_pn}` + + if [ $? -ne 0 ]; then + eerror "${obj} links to ${link}" + eindent + eerror Missing dependency on $(bold ${libowner_pn}) + eoutdent + errors=1 + fi + + + done + + done + + local ebuild_rdepends=() + for rdepend in $(qdepends --nocolor --quiet --rdepend ${atom} | sed -e "s/\[[^]]*\]//g" | cut -d : -f 2-) + do + ebuild_rdepends+=( $(remove_atom_version $rdepend) ) + done + + debug "Ebuild RDEPENDS: ${ebuild_rdepends[@]}" + debug "Linked RDEPENDS: ${rdepends[@]}" + + local suspect_rdepends=$(comm -13 <(echo ${rdepends[@]} | sed 's/ /\n/g' | sort -u) <(echo ${ebuild_rdepends[@]} | sed 's/ /\n/g' | sort -u)) + if [ "${suspect_rdepends}" ]; then + ewarn "Suspect RDEPEND: $(bold ${suspect_rdepends})" + fi + + echo + eoutdent + + return $errors + +} + +check_package() { + + local package=$1 + local atoms=`qlist -IcCS ${package} | tr ' ' '-' | cut -d : -f1` + + debug Package ${package} own atoms: ${atoms} + + if [ ! "${atoms}" ]; then + eerror ERROR: ${package} is not a valid atom + exit 1 + fi + + for atom in ${atoms}; do + check_atom ${atom} + done + +} + +check_category() { + + local errors=0 + + for package in `ls "${PKG_DIR}/${1}"`; do + + check_package "${1}/${package}" + + if [ $? -ne 0 ]; then + errors=1 + fi + + done; + + return $errors + +} + +BINNAME=`basename ${0}` +if [ -z $1 ]; then + echo "Checks emerged package(s) for undeclared depedencies" + echo + echo "Usage: ${BINNAME} [ atom | -c category | -a ]" + echo + echo "Examples:" + echo "Check a single package: ${BINNAME} app-foo/bar-1.2.3" + echo "Check a category: ${BINNAME} -c app-foo" + echo "Check everything: ${BINNAME} -a" + exit 1 +fi + +# check a particular category +if [ "$1" = "-c" ]; then + + CAT=$2 + + if [ ! -d "${PKG_DIR}/${CAT}" ]; then + eerror ERROR: No packages from the category ${CAT} have been emerged yet + exit 1 + fi + + check_category $CAT + +# check everything +elif [ "$1" = "-a" ]; then + + for category in `ls ${PKG_DIR}`; do + check_category $category + done; + +else + check_package $1 +fi + +if [ $? -eq 0 ]; then + einfo Checking complete, no errors found +else + eerror Checking complete, errors found +fi