From 2e7c359b8c03b8f4aba8ced8107d27ee9bec741d Mon Sep 17 00:00:00 2001 From: mudler Date: Sat, 10 Sep 2016 14:41:06 +0200 Subject: [PATCH] add dynlink scanner --- Makefile | 5 ++++- dynlink-scanner | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ try_dlopen.c | 23 +++++++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 dynlink-scanner create mode 100644 try_dlopen.c diff --git a/Makefile b/Makefile index b53cd6d..329030d 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,10 @@ install: install -d $(DESTDIR)/$(USBINDIR) install -m 0755 builder $(DESTDIR)/$(USBINDIR)/ - install -m 0755 depcheck $(DESTDIR)/$(USBINDIR)/ + install -m 0755 depcheck $(DESTDIR)/$(UBINDIR)/ + install -m 0755 dynlink-scanner $(DESTDIR)/$(UBINDIR)/ + gcc try_dlopen.c -o try_dlopen -ldl + install -m 0755 try_dlopen $(DESTDIR)/$(UBINDIR)/ install -d $(DESTDIR)/$(UBINDIR) install -m 0755 sabayon-* $(DESTDIR)/$(UBINDIR)/ diff --git a/dynlink-scanner b/dynlink-scanner new file mode 100644 index 0000000..7a0ed9c --- /dev/null +++ b/dynlink-scanner @@ -0,0 +1,49 @@ +#!/bin/bash + +# Returns colon separated list of linking dependencies +get_link_deps() +{ + KEY= + for dep in `scanelf --use-ldpath -yBF '%f %n' "$1"`; do + if [[ -z $KEY ]]; then + KEY="$dep" + continue + fi + echo $dep + done +} + +# Print linking deps for given executable or shared object in alphabetical order. +# Also try to dlopen shared objects in order to detect missing/broken dependencies. +if [[ "$1" = --linking-deps ]]; then + # Sanity check, file-5.12 is broken, bail out early + if [[ `file --version | grep --color=never file- | cut -d'-' -f2` == '5.12' ]]; then + echo "file-5.12 is broken, bailing out" + exit 1 + fi + mime=`file -b --mime-type "$2"` + if [[ "$mime" == 'application/x-executable' ]] || [[ "${mime}" == 'application/x-sharedlib' ]]; then + LINK=`get_link_deps "$2"` + [[ "$mime" == 'application/x-sharedlib' ]] && /usr/bin/try_dlopen "$2" + [[ -n $LINK ]] && echo -e ${LINK//,/\\n} | sort -u + exit 0 + fi + exit 1 +fi + +[[ -z $* ]] && echo "usage: `basename $0` " && exit 0 + +# Check whether package is installed +if ! portageq has_version $ROOT/ $1; then + echo "$1 is not installed" + exit 1 +fi + +# For each installed slot +for cpv in `portageq match $ROOT/ $1`; do + echo "Processing $cpv" + # For each file that belongs to package + # run dynlink-scanner --linking-deps to obtain its linking dependencies + # Assign all linking deps to packages and print package names + qfile -eR $ROOT `portageq contents $ROOT/ $cpv | xargs -r -L 1 "$0" --linking-deps` | cut -f1 -d' ' | sort -u +done diff --git a/try_dlopen.c b/try_dlopen.c new file mode 100644 index 0000000..7ff6958 --- /dev/null +++ b/try_dlopen.c @@ -0,0 +1,23 @@ +#include +#include + +/** + * Attempts to load shared libraries + * @param argc + * @param argv files to check (pass only shared libs) + * @return 0 - all shared libs loaded, 1 - error occured (invalid or broken files passed) + */ +int main(int argc, char* argv[]) +{ + int i; + for (i = 1; i < argc; ++i) { + void* handle = dlopen(argv[i], RTLD_NOW); + if (!handle) { + fprintf(stderr, "%s\n", dlerror()); + return 1; + } else { + dlclose(handle); + } + } + return 0; +}