commit 73bd9636d0e76a4d255776b7733667198b9ef585 Author: Panu Matilainen 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 };