Bug 12849

Summary: Shared library version script gives warnings from rtld
Product: Base System Reporter: mikko <mikko>
Component: binAssignee: John Polstra <jdp>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.0-CURRENT   
Hardware: Any   
OS: Any   

Description mikko 1999-07-28 13:30:01 UTC
When creating shared libs using version scripts (the --version-script
flag to "ld"), I get warning messages on stdout, presumably from
"rtld-elf", about unsupported "d_tag".

The purpose of using the version script is to limit the number of
externally visible symbols in the lib, but even an almost empty
version script gives this result.

The offending tags seem to be in the range (in hex) 6FFFFFF[0-F]

I have no idea whether the problem lies with rtld or ld, or simply
is a user error.  Programs seem to run ok, though.  For example:

LD_LIBRARY_PATH=. ./program
Ignored d_tag 1879048190
Ignored d_tag 1879048191
Ignored d_tag 1879048176
Ignored d_tag 1879048188
Ignored d_tag 1879048189
Ignored d_tag 1879048176
In main
...

Fix: 

Ask an ELF guru...?
How-To-Repeat: 
Put this makefile in an otherwise empty directory, and run make.  That
should produce a minimal shared lib and a minimal program linked
against it, as well as run the program to show the diagnostics.

"make clean; make NOVERSION=yes" repeats the operation, but without
the version script and without diagnostics from rtld.

---8<--Makefile --------------------------------------------------------------
.ifndef NOVERSION
LD_FLAGS = -Wl,--version-script=version
.endif

CFLAGS = -fpic
OTHERLIBS = -lc

program: program.o
	$(CC) -o $@ $? -L. -lxxx
	LD_LIBRARY_PATH=. ./program

program: libxxx.so

program.c: mkfunc.sh
	sh mkfunc.sh main entry > $@

libxxx.so: libxxx.so.1
	ln -sf $? $@

libxxx.so.1: f.o version
	cc -shared -o $@ -Wl,-soname,$@ f.o $(LD_FLAGS) $(OTHERLIBS)

f.c: mkfunc.sh
	sh mkfunc.sh entry > $@

version:
	echo 'V_1.0 { global: entry; local: *; };' > $@

mkfunc.sh:
	(echo 'echo -n "int $$1() { puts(\"In $$1\");"; shift;';\
	 echo 'for i in $$*; do echo -n "$$i();"; done';\
	 echo 'echo "return 0; }";'; ) > mkfunc.sh

clean:
	rm -f *.c *.o *.a *.so *.so.? program version mkfunc.sh *.core
---8<----------------------------------------------------------------------
Comment 1 Sheldon Hearn freebsd_committer freebsd_triage 1999-07-28 16:36:08 UTC
Responsible Changed
From-To: freebsd-bugs->jb

John is an ELF guru. John, if I'm treading on your toes here, please 
feel free to say so. :-) 

Comment 2 mikko 1999-08-02 09:13:41 UTC
FWIW: It works w/o warnings on linux, using the same compiler and
      almost the same linker.

m% uname -a ; ld -v; cc --version 
Linux m.dynas.se 2.2.5-15 #1 Mon Apr 19 22:21:09 EDT 1999 i586 unknown
GNU ld version 2.9.1 (with BFD 2.9.1.0.23)
egcs-2.91.66

	/Mikko
Comment 3 Sheldon Hearn freebsd_committer freebsd_triage 1999-08-02 11:34:01 UTC
Responsible Changed
From-To: jb->jdp

John points out that John Polstra should have been the man I chose 
to bug. :-) 

Comment 4 mikko 1999-08-31 15:15:18 UTC
Sheldon,

On Mon, 30 Aug 1999, Sheldon Hearn wrote:

> Could you test for the existance of the problem you reported on PR 12849
> when next you ``make world'' and install an updated kernel? I see John's
> done a little work in this area recently.


Short answer: Nope.

Long answer:

 I still haven't found an ELF spec anywhere on the net, but looking at
 the GNU ld documentation & code, I think I know what is going on:
 
 The 0x6ffffffx tags are invented by Sun, adopted by GNU, and are used
 for the version stuff (as described by the "version script").
 
 The purpose of the version symbols is to allow the dynamic linker to check
 that a library contains the version(s) that the program needs
 directly when the library is loaded, rather than during symbol lookup,
 which may be deferred with RTLD_LAZY. (This is the way it works
 on Solaris)
 
 A quick workaround would be to define the symbols needed (see
 contrib/binutils/include/elf/common.h), so rtld can at least
 silently ignore them.
 
 As far as I can tell (the GNU ld code is a bit messy) rtld does not
 actually have to apply any logic to the symbol bindings, so ignoring
 the version information would just revert to the normal error
 messages about undefined symbols if the library is incompatible,
 though maybe not at load time.
 
 As it is right now, version scripts are unusable on FreeBSD (I don't
 really need versions per se -- I just need to limit the exposed
 API), which means I cannot provide the products we are working on for
 FreeBSD, unless we do some kind of hack :(


	Regards,
	/Mikko

 Mikko Tyo"la"ja"rvi________________________________mikko@securitydynamics.com
 SecurityDynamics
Comment 5 John Polstra 1999-08-31 17:00:53 UTC
Mikko Työläjärvi wrote:

>   A quick workaround would be to define the symbols needed (see
>   contrib/binutils/include/elf/common.h), so rtld can at least
>   silently ignore them.

I don't mind eliminating the warning.  I could put it inside an
"#ifdef DEBUG" so that it's still available to developers working on
the dynamic linker.  That would solve your problem, correct?  Please
let me know.  I can commit that simple change to -current and
-stable immediately.

>   As far as I can tell (the GNU ld code is a bit messy)

The pope is a bit of a Catholic.  The Pacific Ocean has a bit of
water in it.  The sun is a bit warm. ;-)

>   rtld does not actually have to apply any logic to the symbol
>   bindings, so ignoring the version information would just revert to
>   the normal error messages about undefined symbols if the library
>   is incompatible, though maybe not at load time.

I haven't really looked into the symbol versioning feature yet, but
your statement sounds sensible to me.

>   As it is right now, version scripts are unusable on FreeBSD (I
>   don't really need versions per se -- I just need to limit the
>   exposed API), which means I cannot provide the products we are
>   working on for FreeBSD, unless we do some kind of hack :(

For a hack to limit the exposed API, look at some of the options for
"objcopy".  It has features to hide specified symbols.  If you decide
to use it, though, be forewarned that Poul-Henning Kamp found what
appears to be a bug in objcopy.  He supplied me with this patch, which
apparently makes it work right:

Index: objcopy.c
===================================================================
RCS file: /home/ncvs/src/contrib/binutils/binutils/objcopy.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 objcopy.c
--- objcopy.c   1998/09/06 22:56:57     1.1.1.2
+++ objcopy.c   1999/07/04 23:56:24
@@ -544,6 +544,8 @@
                    && (discard_locals != locals_start_L
                        || ! bfd_is_local_label (abfd, sym))));
 
+      if (strip_symbols == strip_all)
+        keep = 0;
       if (keep && is_specified_symbol (name, strip_specific_list))
        keep = 0;
       if (!keep && is_specified_symbol (name, keep_specific_list))
@@ -779,7 +781,7 @@
 
   /* Symbol filtering must happen after the output sections have
      been created, but before their contents are set.  */
-  if (strip_symbols == strip_all)
+  if (strip_symbols == strip_all && keep_specific_list == NULL) 
     {
       osympp = isympp = NULL;
       symcount = 0;


John
---
  John Polstra                                               jdp@polstra.com
  John D. Polstra & Co., Inc.                        Seattle, Washington USA
  "No matter how cynical I get, I just can't keep up."        -- Nora Ephron
Comment 6 John Polstra freebsd_committer freebsd_triage 1999-09-04 21:15:27 UTC
State Changed
From-To: open->closed

Fixed in "src/libexec/rtld-elf/rtld.c" revison 1.38.  I used your 
suggested work-around and simply disabled the warnings.  Since this 
was such a simple change, I will ask the release engineer for 
permission to merge it into the upcoming 3.3-RELEASE as well. 

I'll investigate the possibility of actually supporting symbol 
versioning in the future. 

Thanks very much for the excellent test case you provided.  That 
was a real time-saver!