From patchwork Fri Apr 22 20:50:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Samuel Martin X-Patchwork-Id: 613860 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by ozlabs.org (Postfix) with ESMTP id 3qs77p6VTCz9sDD for ; Sat, 23 Apr 2016 06:51:18 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=tjxt/XCG; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 2A5B0966B2; Fri, 22 Apr 2016 20:51:17 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PSoWIiHV0kZn; Fri, 22 Apr 2016 20:51:03 +0000 (UTC) Received: from ash.osuosl.org (ash.osuosl.org [140.211.166.34]) by hemlock.osuosl.org (Postfix) with ESMTP id 21D51966A3; Fri, 22 Apr 2016 20:50:53 +0000 (UTC) X-Original-To: buildroot@lists.busybox.net Delivered-To: buildroot@osuosl.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by ash.osuosl.org (Postfix) with ESMTP id 08AC31C1750 for ; Fri, 22 Apr 2016 20:50:46 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 062C5C002F for ; Fri, 22 Apr 2016 20:50:46 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id KZftRJxeENkg for ; Fri, 22 Apr 2016 20:50:45 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by fraxinus.osuosl.org (Postfix) with ESMTPS id 0B121C05F0 for ; Fri, 22 Apr 2016 20:50:45 +0000 (UTC) Received: by mail-wm0-f67.google.com with SMTP id n3so7846959wmn.1 for ; Fri, 22 Apr 2016 13:50:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Y2lQYFuu0MeVT1bXIZGtZRqlt2OaS4DRrUZPbc14Azg=; b=tjxt/XCG2UFMKLm5jPIDIMGNLeCcfFQX96YzllHo6szsYfIEjPl7jBbx04Qj/9MzU+ HWdIMIrmhwAUfE1qEloothJaOxhr+L7lJc26ZdzvDpGbtZ0Rg6cU+q1qaca5qVHespg3 orEiNZvS3uEg1ioRDVt3mvEfk/akjtBhs0gXhWRn6Opid2ck426cGqdrUFgOtv+Xe6qs zyomtwzUWvBIhF84t1qQgXZpPa72sRLtt3ZBldy9Pz6MuwnlRatMMlb3CBZEyR5GHt25 LunL0KjeS8qsCivXisbJg9D5E/1/viPSUW5T9/W8glMuOJ/UWK/fq1VHo+Ea2Z9W9xJp gMSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Y2lQYFuu0MeVT1bXIZGtZRqlt2OaS4DRrUZPbc14Azg=; b=Yz2wMuDfPZBnRnnrxv8/uTMSdbUIkD60HE+/Fq3b3VBsxf2kUGZQKrsI1SbEOtEcP4 zG2KLzPAIy3EUIwbAHPyDqsKwShryVukTViG4WHMFx/19Hax537jq5VpVwwSfsJS50OO VEUWKACsfEoDir4YXrK1yBfmZpWFU2rgANvypcz80HvswPORGmIzVAAppefb9MEikpzI iY+wCJPVeUUYWExoMUXlaDh9dA/boI5uXu17fzILiNiOOY2Sj0DpOM1ffECp1ZknQbtZ jEwsO62t+DvN3E05uKc7kkNl1NNTE5ZZdybhtaI4Hvkgw/wKEjmyE1qdQ20KHH2Tul61 FtOA== X-Gm-Message-State: AOPr4FUWmbE33QxwrUY5VRA88hfVZ12rhYjmQffSZiBVrpUYQUhcTc2zlMPhSTc3CcMwDA== X-Received: by 10.28.211.136 with SMTP id k130mr5553005wmg.81.1461358243698; Fri, 22 Apr 2016 13:50:43 -0700 (PDT) Received: from bobook.localdomain (ivr94-4-82-229-165-48.fbx.proxad.net. [82.229.165.48]) by smtp.gmail.com with ESMTPSA id iv1sm9826507wjb.34.2016.04.22.13.50.41 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 22 Apr 2016 13:50:42 -0700 (PDT) From: Samuel Martin To: buildroot@buildroot.org Date: Fri, 22 Apr 2016 22:50:19 +0200 Message-Id: <1461358223-18312-8-git-send-email-s.martin49@gmail.com> X-Mailer: git-send-email 2.8.0 In-Reply-To: <1461358223-18312-1-git-send-email-s.martin49@gmail.com> References: <1461358223-18312-1-git-send-email-s.martin49@gmail.com> Cc: "Yann E. MORIN" Subject: [Buildroot] [PATCH v9 07/11] support/scripts: update check-host-rpath to use the shell helpers X-BeenThere: buildroot@busybox.net X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: Discussion and development of buildroot List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: buildroot-bounces@busybox.net Sender: "buildroot" This change moves and refactors the helper functions from the check-host-rpath into the readelf module. The replacement of the elf_needs_rpath function: readelf.needs_rpath does not fundamentally change the implementation, it only uses the APIs offered by the readelf module. The replacement of the check_elf_has_rpath function: readelf.has_rpath does a bit more than the original implementation - adding the support for relative RPATH (those strating with '$ORIGIN'). Cc: "Yann E. MORIN" Signed-off-by: Samuel Martin --- changes v8->v9: - update commit log (ThomasP) - minor fix changes v7->v8: - none changes v6->v7: - minor updates after shell modules shell changes changes v5->v6: - new patch --- support/scripts/check-host-rpath | 73 +++++++++++++++------------------------- support/scripts/shell/readelf.sh | 69 +++++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 45 deletions(-) diff --git a/support/scripts/check-host-rpath b/support/scripts/check-host-rpath index 6ce547c..e6e82d6 100755 --- a/support/scripts/check-host-rpath +++ b/support/scripts/check-host-rpath @@ -1,12 +1,29 @@ #!/usr/bin/env bash +# Copyright (C) 2015 Yann E. MORIN +# Copyright (C) 2016 Samuel Martin +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + # This script scans $(HOST_DIR)/{bin,sbin} for all ELF files, and checks # they have an RPATH to $(HOST_DIR)/usr/lib if they need libraries from # there. -# Override the user's locale so we are sure we can parse the output of -# readelf(1) and file(1) -export LC_ALL=C +source "${0%/*}/shell/source.sh" + +source.load_module readelf main() { local pkg="${1}" @@ -14,58 +31,24 @@ main() { local file ret # Remove duplicate and trailing '/' for proper match - hostdir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${hostdir}" )" + hostdir="$(sed -r -e 's:/+:/:g; s:/$::;' <<<"${hostdir}")" ret=0 while read file; do - elf_needs_rpath "${file}" "${hostdir}" || continue - check_elf_has_rpath "${file}" "${hostdir}" && continue + READELF=readelf readelf.needs_rpath "${file}" "${hostdir}" || continue + READELF=readelf readelf.has_rpath "${file}" "${hostdir}" && continue if [ ${ret} -eq 0 ]; then ret=1 printf "***\n" - printf "*** ERROR: package %s installs executables without proper RPATH:\n" "${pkg}" + printf \ + "*** ERROR: package %s installs executables without proper RPATH:\n" \ + "${pkg}" fi printf "*** %s\n" "${file}" - done < <( find "${hostdir}"/{,usr/}{bin,sbin} -type f -exec file {} + 2>/dev/null \ - |sed -r -e '/^([^:]+):.*\.*\.*/!d' \ - -e 's//\1/' \ - ) + done < <(find "${hostdir}"/{,usr/}{bin,sbin} -type f -print 2>/dev/null | + readelf.filter_elf_executable) return ${ret} } -elf_needs_rpath() { - local file="${1}" - local hostdir="${2}" - local lib - - while read lib; do - [ -e "${hostdir}/usr/lib/${lib}" ] && return 0 - done < <( readelf -d "${file}" \ - |sed -r -e '/^.* \(NEEDED\) .*Shared library: \[(.+)\]$/!d;' \ - -e 's//\1/;' \ - ) - - return 1 -} - -check_elf_has_rpath() { - local file="${1}" - local hostdir="${2}" - local rpath dir - - while read rpath; do - for dir in ${rpath//:/ }; do - # Remove duplicate and trailing '/' for proper match - dir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${dir}" )" - [ "${dir}" = "${hostdir}/usr/lib" ] && return 0 - done - done < <( readelf -d "${file}" \ - |sed -r -e '/.* \(R(UN)?PATH\) +Library r(un)?path: \[(.+)\]$/!d' \ - -e 's//\3/;' \ - ) - - return 1 -} - main "${@}" diff --git a/support/scripts/shell/readelf.sh b/support/scripts/shell/readelf.sh index c8ad38b..78a1a9f 100644 --- a/support/scripts/shell/readelf.sh +++ b/support/scripts/shell/readelf.sh @@ -24,11 +24,15 @@ # readelf.is_elf_executable # readelf.is_elf_shared_object # readelf.get_rpath +# readelf.get_neededs +# readelf.needs_rpath +# readelf.has_rpath # readelf.list_sections # readelf.has_section # # This module is sensitive to the following environment variables: # READELF + source.declare_module readelf # When calling readelf(1) program, the user's locale will be overriden with the @@ -143,6 +147,71 @@ readelf.get_rpath() { sed -r -e '/.* \(R(UN)?PATH\) +Library r(un)?path: \[(.+)\]$/!d ; s//\3/' } +# readelf.get_neededs file +# +# Returns the list of the NEEDED libraries of $file. +# +# file : ELF file path +# +# environment: +# READELF: readelf program path +readelf.get_neededs() { + local file="${1}" + LC_ALL=C "${READELF}" --dynamic "${file}" | + sed -r -e '/^.* \(NEEDED\) .*Shared library: \[(.+)\]$/!d ; s//\1/' +} + +# readelf.needs_rpath file basedir +# +# Returns 0 if $file needs to have RPATH set, 1 otherwise. +# +# file : path of file to be tested +# basedir : path of the tree in which $basedir/lib and $basedir/usr/lib are +# checked for belonging to RPATH +# +# environment: +# READELF: readelf program path +readelf.needs_rpath() { + local file="${1}" + local basedir="${2}" + local lib + + while read lib; do + [ -e "${basedir}/lib/${lib}" ] && return 0 + [ -e "${basedir}/usr/lib/${lib}" ] && return 0 + done < <(readelf.get_neededs "${file}") + return 1 +} + +# readelf.has_rpath file basedir +# +# Returns 0 if $file has RPATH already set to $basedir/lib or $basedir/usr/lib, +# or uses relative RPATH (starting with "$ORIGIN"); returns 1 otherwise. +# +# file : path of file to be tested +# basedir : path of the tree in which $basedir/lib and $basedir/usr/lib are +# checked for belonging to RPATH +# +# environment: +# READELF: readelf program path +readelf.has_rpath() { + local file="${1}" + local basedir="${2}" + local rpath dir + + while read rpath; do + for dir in ${rpath//:/ }; do + # Remove duplicate and trailing '/' for proper match + dir="$(sed -r -e "s:/+:/:g; s:/$::" <<<"${dir}")" + [ "${dir}" = "${basedir}/lib" ] && return 0 + [ "${dir}" = "${basedir}/usr/lib" ] && return 0 + grep -q '^\$ORIGIN/' <<<"${dir}" && return 0 + done + done < <(readelf.get_rpath "${file}") + + return 1 +} + # readelf.list_sections file # # Returns the list of ELF sections in $file.