Blob Blame History Raw
commit 73bd9636d0e76a4d255776b7733667198b9ef585
Author: Panu Matilainen <pmatilai@redhat.com>
Date:   Mon Jan 7 15:52:43 2013 +0200

    Filter ELF dependencies by name
    
    - Instead of vain heuristics on DT_SONAME presence, filter out
      irregular sonames from all dependencies: linkable library names generally
      must contain ".so" and start with "lib" for the linker to find it at all,
      anything else is an exception of one kind or another (the prime exception
      of ld.so variants we handle here). This weeds out provides for most
      dlopen()'ed modules etc, and filtering both provides and requires
      by the same rules means we wont generate requires for things that wont be
      provided.  Of course this also means we can omit things that are in
      DT_NEEDED, but these should be rare exceptions which the new
      --no-filter-soname switch is for.

diff --git a/tools/elfdeps.c b/tools/elfdeps.c
index fc9a905..a0db9f7 100644
--- a/tools/elfdeps.c
+++ b/tools/elfdeps.c
@@ -15,6 +15,7 @@
 int filter_private = 0;
 int soname_only = 0;
 int fake_soname = 1;
+int filter_soname = 1;
 
 typedef struct elfInfo_s {
     Elf *elf;
@@ -36,6 +37,31 @@ static int skipPrivate(const char *s)
     return (filter_private && rstreq(s, "GLIBC_PRIVATE"));
 }
 
+/*
+ * Rough soname sanity filtering: all sane soname's dependencies need to
+ * contain ".so", and normal linkable libraries start with "lib",
+ * everything else is an exception of some sort. The most notable
+ * and common exception is the dynamic linker itself, which we allow
+ * here, the rest can use --no-filter-soname.
+ */
+static int skipSoname(const char *soname)
+{
+    if (filter_soname) {
+	if (!strstr(soname, ".so"))
+	    return 1;
+
+	if (rstreqn(soname, "ld.", 3) || rstreqn(soname, "ld-", 3))
+	    return 0;
+
+	if (rstreqn(soname, "lib", 3))
+	    return 0;
+	else
+	    return 1;
+    }
+
+    return 0;
+}
+
 static const char *mkmarker(GElf_Ehdr *ehdr)
 {
     const char *marker = NULL;
@@ -58,6 +84,10 @@ static void addDep(ARGV_t *deps,
 		   const char *soname, const char *ver, const char *marker)
 {
     char *dep = NULL;
+
+    if (skipSoname(soname))
+	return;
+
     if (ver || marker) {
 	rasprintf(&dep,
 		  "%s(%s)%s", soname, ver ? ver : "", marker ? marker : "");
@@ -293,6 +323,7 @@ int main(int argc, char *argv[])
 	{ "filter-private", 0, POPT_ARG_VAL, &filter_private, -1, NULL, NULL },
 	{ "soname-only", 0, POPT_ARG_VAL, &soname_only, -1, NULL, NULL },
 	{ "no-fake-soname", 0, POPT_ARG_VAL, &fake_soname, 0, NULL, NULL },
+	{ "no-filter-soname", 0, POPT_ARG_VAL, &filter_soname, 0, NULL, NULL },
 	POPT_AUTOHELP 
 	POPT_TABLEEND
     };