ld magic: -Bgroup

Lutz Birkhahn lbirkhahn@adomo.com
Fri Nov 3 08:20:00 GMT 2006


Not sure if I completely understand the concept of -Bgroup, but I thought
it would solve my problem:

Let's say I have two 3rd-party shared libraries, libA and libB. Both of
these reference another function libC_func(), which is defined in other
shared libraries (libCommonA.so for libA, libCommonB.so for libB).

Now I need to link my program to both libA and libB, and each of the
libraries should use their own version of libC_func(), and not a common
one. Isn't that what the -Bgroup option of ld is supposed to do?

In ASCII art:

       /-- libA.so --- libCommonA.so --- libC_func()
prog -
       \-- libB.so --- libCommonB.so --- libC_func()

So I'm trying to compile libA with this command:

   gcc -shared -Wl,-Bgroup -o libA.so libA.c -L. -lCommonA /lib/ld-2.3.4.so

and libB is compiled like this:

   gcc -shared -Wl,-Bgroup -o libB.so libB.c -L. -lCommonB /lib/ld-2.3.4.so

The main program, "prog" is compiled with this command:

   gcc -o prog prog.c -L libA -lA -L libB -lB

But when I run the program, it's in both cases using libA's libC_func().
When I use the -Bgroup switch, isn't the linker supposed to satisfy all
of libB's references from that library's group?

objdump -x libB.so tells me that it needs libCommonB.so, and in the
"Dynamic Section" it has "FLAGS_1  0x4" (that's from the -Bgroup,
right?). Running the program with strace tells me that it is actually
loading both libCommonA and libCommonB, but it's still only using the
function from the first one (or the other way around if I set my
LD_LIBRARY_PATH to search in libB's directory first).

I have attached a test program as tar file, just go to the top direc-
tory and run make, and then "./prog".

gcc version: 4.0.2
ld version: 2.15.92.0.2 20040927
(This is on a RHEL4 system)

I'm puzzled now. Any hints what's wrong?

/lutz


In case attachments are stripped off, here are the contents of the files:

--------------- Makefile ---------------
# Makefile

prog: libA/libA.so libB/libB.so prog.c
        gcc -o prog prog.c \
          -L libA -lA \
          -L libB -lB

libA/libA.so:
        make -C libA

libB/libB.so:
        make -C libB

clean:
        make -C libA clean
        make -C libB clean
        rm -f prog

--------------- prog.c ---------------
/* prog.c */

#include <stdio.h>
#include "libA/libA.h"
#include "libB/libB.h"

int main (int ac, char **av)
{
  printf ("prog calling libA_func()\n");
  libA_func();
  printf ("prog calling libB_func()\n");
  libB_func();
  printf ("prog done\n");
  return 0;
}

--------------- libA/Makefile ---------------
# libA/Makefile

libA.so: libA.c libCommonA.so
        gcc -shared -Wl,-Bgroup -o libA.so libA.c -L. 
-lCommonA /lib/ld-2.3.4.so

libCommonA.so: libCommonA.c
        gcc -shared -Wl,-Bgroup -o libCommonA.so libCommonA.c /lib/ld-2.3.4.so

clean:
        rm -f *.so

--------------- libA/libA.h ---------------
/* libA/libA.h */

void libA_func();

--------------- libA/libA.c ---------------
/* libA/libA.c */

#include <stdio.h>
#include "libCommonA.h"

void libA_func ()
{
  printf ("libA_func() calling libC_func\n");
  libC_func();
}

--------------- libA/libCommonA.h ---------------
/* libA/libCommonA.h */

void libC_func();

--------------- libA/libCommonA.c ---------------
/* libA/libCommonA.c */

#include <stdio.h>

void libC_func ()
{
  printf ("libA's libC_func\n");
}

--------------- libB/Makefile ---------------
# libB/Makefile

libB.so: libB.c libCommonB.so
        gcc -shared -Wl,-Bgroup -o libB.so libB.c -L. 
-lCommonB /lib/ld-2.3.4.so

libCommonB.so: libCommonB.c
        gcc -shared -Wl,-Bgroup -o libCommonB.so libCommonB.c /lib/ld-2.3.4.so

clean:
        rm -f *.so

--------------- libB/libB.h ---------------
/* libB/libB.h */

void libB_func();

--------------- libB/libB.c ---------------
/* libB/libB.c */
#include <stdio.h>
#include "libCommonB.h"

void libB_func ()
{
  printf ("libB_func() calling libC_func\n");
  libC_func();
}

--------------- libB/libCommonB.h ---------------
/* libB/libCommonB.h */

void libC_func();

--------------- libB/libCommonB.c ---------------
/* libB/libCommonB.c */

#include <stdio.h>

void libC_func ()
{
  printf ("libB's libC_func\n");
}

------------------------------

Current output:

$ ./prog
prog calling libA_func()
libA_func() calling libC_func
libA's libC_func
prog calling libB_func()
libB_func() calling libC_func
libA's libC_func    <=============
prog done

In the second to last line I expected to see "libB's libC_func", not
libA's.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Bgroup_test.tgz
Type: application/x-tgz
Size: 929 bytes
Desc: not available
URL: <https://sourceware.org/pipermail/binutils/attachments/20061103/1d0ef2e1/attachment.bin>


More information about the Binutils mailing list