This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[BUG] runpath broken for .so's in ld


The runpath of a shared object is not always being
searched when linking an executable.

The behavior I'm seeing is the following:
  I have an external library (libext1.so), which lives
in ~/ext1.
  A shared library (libfoo.so) is created which links
against libext.so and records a DT_RUNPATH for ~/ext1.
  Another shared library (libbar.so) is created with a
DT_RUNPATH for some other directory (ext2/libext2.so).
  I attempt to create a binary (baz) that links
against libfoo, and libbar.
  The link fails as libext1 cannot be found.

Just to codify the above:

mkdir ext1;
mkdir ext2;

dummy.c:
        /* empty */

main.c:
        int main() { return 0; }

Makefile:
        ext1/libext1.so: dummy.c
                gcc -shared dummy.c -o $@

        ext2/libext2.so: dummy.c
                gcc -shared dummy.c -o $@

        libfoo.so: ext1/libext1.so
                gcc -shared -Lext1 -Wl,-rpath,ext1
-Wl,--enable-new-dtags -lext1 -o $@

        libbar.so: ext2/libext2.so
                gcc -shared -Lext2 -Wl,-rpath,ext2
-Wl,--enable-new-dtags -lext2 -o $@

        baz: main.c libbar.so libfoo.so
                gcc main.c -L. -Wl,-rpath,. -lfoo
-lbar -o $@

make baz


Looking at the source I see in elflink.h:
        /* When we see DT_RPATH before DT_RUNPATH, we
have
           to clear runpath.  Do _NOT_ bfd_release, as
that
           frees all more recently bfd_alloc'd blocks
as
           well.  */
        if (rpath && hash_table->runpath)
            hash_table->runpath = NULL;


but this clears all the runpath info during a link as
the hash table from the info is shared.
In eelf_i386.c:
        rp = bfd_elf_get_runpath_list (output_bfd,
&link_info);
        for (; !found && rp != NULL; rp = rp->next)
          {
            found = (rp->by == l->by
                && gldelf_i386_search_needed
(rp->name,
                                   l->name,
                                   force));

With the runpath-clearing line commented out, my
example works.  With it, it fails with:
        warning: libext1.so, needed by ./libfoo.so,
not found (try using -rpath, or -rpath-link)

Peppering printf's in eelf_i386.c shows that it only
sees the runpath entries from libbar.so.

This is with binutils-2.13.90.0.10 on a Linux
2.4.18/glibc 2.2.5/P4 using
gcc 2.95.2.

Thanks,
-Kenny

__________________________________________________
Do you Yahoo!?
Faith Hill - Exclusive Performances, Videos & More
http://faith.yahoo.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]