Skip to content

Commit

Permalink
Issue #403: Don't generate an error if we're analysing a shared
Browse files Browse the repository at this point in the history
library (indicated by the presence of a DT_SONAME tag) and not all the
NEEDED resolve to files successfully.  Shared libraries can
legitimately use dynamic link information from the applications that
link against them in order to resolve all their dependencies
correctly.
  • Loading branch information
infracaninophile committed Dec 20, 2012
1 parent 7b56ebc commit d174f74
Showing 1 changed file with 40 additions and 14 deletions.
54 changes: 40 additions & 14 deletions libpkg/pkg_elf.c
Expand Up @@ -65,6 +65,7 @@ filter_system_shlibs(const char *name, char *path, size_t pathlen)

shlib_path = shlib_list_find_by_name(name);
if (shlib_path == NULL) {
/* dynamic linker could not resolve */
return (EPKG_FATAL);
}

Expand All @@ -73,10 +74,6 @@ filter_system_shlibs(const char *name, char *path, size_t pathlen)
strncmp(shlib_path, "/usr/lib", 7) == 0)
return (EPKG_END); /* ignore libs from base */

/* When running in DEVELOPER_MODE check that shlib names
* conform to the correct pattern. Only warn on error --
* shlibs may belong to a different package. */

if (path != NULL)
strncpy(path, shlib_path, pathlen);

Expand All @@ -88,14 +85,16 @@ filter_system_shlibs(const char *name, char *path, size_t pathlen)
/* ARGSUSED */
static int
do_nothing(__unused void *actdata, __unused struct pkg *pkg,
__unused const char *fpath, __unused const char *name)
__unused const char *fpath, __unused const char *name,
__unused bool is_shlib)
{
return (EPKG_OK);
}

/* ARGSUSED */
static int
add_shlibs_to_pkg(__unused void *actdata, struct pkg *pkg, const char *fpath, const char *name)
add_shlibs_to_pkg(__unused void *actdata, struct pkg *pkg, const char *fpath,
const char *name, bool is_shlib)
{
switch(filter_system_shlibs(name, NULL, 0)) {
case EPKG_OK: /* A non-system library */
Expand All @@ -104,14 +103,20 @@ add_shlibs_to_pkg(__unused void *actdata, struct pkg *pkg, const char *fpath, co
case EPKG_END: /* A system library */
return (EPKG_OK);
default:
/* Ignore link resolution errors if we're analysing a
shared library. */
if (is_shlib)
return (EPKG_OK);

warnx("(%s-%s) %s - shared library %s not found",
pkg_name(pkg), pkg_version(pkg), fpath, name);
return (EPKG_FATAL);
}
}

static int
test_depends(void *actdata, struct pkg *pkg, const char *fpath, const char *name)
test_depends(void *actdata, struct pkg *pkg, const char *fpath,
const char *name, bool is_shlib)
{
struct pkgdb *db = actdata;
struct pkg_dep *dep = NULL;
Expand All @@ -133,6 +138,11 @@ test_depends(void *actdata, struct pkg *pkg, const char *fpath, const char *name
case EPKG_END: /* A system library */
return (EPKG_OK);
default:
/* Ignore link resolution errors if we're analysing a
shared library. */
if (is_shlib)
return (EPKG_OK);

warnx("(%s-%s) %s - shared library %s not found",
pkg_name(pkg), pkg_version(pkg), fpath, name);
return (EPKG_FATAL);
Expand Down Expand Up @@ -180,7 +190,7 @@ warn_about_name_format(struct pkg *pkg, const char *fpath, const char *shlib)
unsigned len;

/* Shlib names in NEEDED records in the Dynamic section of an
ELF object are expect to look like libfoo.so.N where the
ELF object are expected to look like libfoo.so.N where the
ABI version N is an integer or libfoo.so without ABI
version at all. */

Expand Down Expand Up @@ -215,8 +225,9 @@ warn_about_name_format(struct pkg *pkg, const char *fpath, const char *shlib)
}

static int
analyse_elf(struct pkg *pkg, const char *fpath,
int (action)(void *, struct pkg *, const char *, const char *), void *actdata)
analyse_elf(struct pkg *pkg, const char *fpath,
int (action)(void *, struct pkg *, const char *, const char *, bool),
void *actdata)
{
Elf *e = NULL;
GElf_Ehdr elfhdr;
Expand All @@ -238,6 +249,7 @@ analyse_elf(struct pkg *pkg, const char *fpath,
bool shlibs = false;
bool autodeps = false;
bool developer = false;
bool is_shlib = false;

pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);
pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
Expand Down Expand Up @@ -333,7 +345,13 @@ analyse_elf(struct pkg *pkg, const char *fpath,
find any RPATH or RUNPATH settings. These are colon
separated paths to prepend to the ld.so search paths from
the ELF hints file. These always seem to come right after
the NEEDED entries */
the NEEDED shared library entries.
NEEDED entries should resolve to a filename for installed
executables, but need not resolve for installed shared
libraries -- additional info from the apps that link
against them would be required. Shared libraries are
distinguished by a DT_SONAME tag */

rpath_list_init();
for (dynidx = 0; dynidx < numdyn; dynidx++) {
Expand All @@ -344,6 +362,9 @@ analyse_elf(struct pkg *pkg, const char *fpath,
goto cleanup;
}

if (dyn->d_tag == DT_SONAME)
is_shlib = true;

if (dyn->d_tag != DT_RPATH && dyn->d_tag != DT_RUNPATH)
continue;

Expand All @@ -352,7 +373,7 @@ analyse_elf(struct pkg *pkg, const char *fpath,
break;
}

/* Now find all of the NEEDED shared libraries */
/* Now find all of the NEEDED shared libraries. */

for (dynidx = 0; dynidx < numdyn; dynidx++) {
if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
Expand All @@ -367,10 +388,15 @@ analyse_elf(struct pkg *pkg, const char *fpath,

shlib = elf_strptr(e, sh_link, dyn->d_un.d_val);

/* When running in DEVELOPER_MODE check that shlib
names conform to the correct pattern. Only issue a
warning on mismatch -- shlibs may belong to a
different package. */

if (developer)
warn_about_name_format(pkg, fpath, shlib);

action(actdata, pkg, fpath, shlib);
action(actdata, pkg, fpath, shlib, is_shlib);
}

cleanup:
Expand Down Expand Up @@ -412,7 +438,7 @@ pkg_analyse_files(struct pkgdb *db, struct pkg *pkg)
bool shlibs = false;
bool autodeps = false;
bool developer = false;
int (*action)(void *, struct pkg *, const char *, const char *);
int (*action)(void *, struct pkg *, const char *, const char *, bool);

pkg_config_bool(PKG_CONFIG_SHLIBS, &shlibs);
pkg_config_bool(PKG_CONFIG_AUTODEPS, &autodeps);
Expand Down

0 comments on commit d174f74

Please sign in to comment.