From andy@silverbrook.com.au  Wed Aug  2 23:01:52 2000
Return-Path: <andy@silverbrook.com.au>
Received: from entoo.connect.com.au (entoo.connect.com.au [192.189.54.8])
	by hub.freebsd.org (Postfix) with ESMTP id F148937B6FA
	for <FreeBSD-gnats-submit@freebsd.org>; Wed,  2 Aug 2000 23:01:50 -0700 (PDT)
	(envelope-from andy@silverbrook.com.au)
Received: from bebop.lan.silverbrook.com.au (CPE-144-132-228-195.nsw.bigpond.net.au [144.132.228.195])
	by entoo.connect.com.au (Postfix) with ESMTP id A85A0DD1FE
	for <FreeBSD-gnats-submit@freebsd.org>; Thu,  3 Aug 2000 16:01:47 +1000 (EST)
Received: (from andy@localhost)
	by bebop.lan.silverbrook.com.au (8.9.3/8.9.3) id QAA20818;
	Thu, 3 Aug 2000 16:01:42 +1000 (EST)
	(envelope-from andy)
Message-Id: <200008030601.QAA20818@bebop.lan.silverbrook.com.au>
Date: Thu, 3 Aug 2000 16:01:42 +1000 (EST)
From: Andy Newman <andy@silverbrook.com.au>
Reply-To: andy@silverbrook.com.au
To: FreeBSD-gnats-submit@freebsd.org
Subject: Setting breakpoints in shared objects broken
X-Send-Pr-Version: 3.2

>Number:         20373
>Category:       bin
>Synopsis:       Setting breakpoints in shared objects broken
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 02 23:10:00 PDT 2000
>Closed-Date:    Sun Jul 31 12:04:20 GMT 2005
>Last-Modified:  Sun Jul 31 12:04:20 GMT 2005
>Originator:     Andy Newman
>Release:        FreeBSD 4.1-STABLE i386
>Organization:
Silverbrook Research
>Environment:

Freshly CVSup'd 4.1-STABLE as of Aug. 3, 13:00 (GMT +10),

$ uname -a
FreeBSD bebop.lan.silverbrook.com.au 4.1-STABLE FreeBSD 4.1-STABLE #0: Thu Aug  3 13:29:45 EST 2000     toor@bebop.lan.silverbrook.com.au:/usr/obj/usr/src/sys/bebop  i386

(i.e., cvsup & make buildworld approx. three hours prior to bug submission)

Problem also occurs on a slighly older 4.0-STABLE (post-release CVSup)
but *does not* occur on a 3.5-STABLE system.

>Description:

	Setting a breakpoint in an run-time loaded object from a
	C or C++ program does not work as expected.  The breakpoint
	appears to be set at the end of the function or at least
	the trap doesn't occur until function exit rather than
	at the breakpoint position.  See following typscript of
	a debug session using the attached sample program which
	loads a shared object and calls a function.  The sample is
	C++ (as that is where I first ran into the problem) but
	compiling it as C (with a couple of little mods) shows
	the same problem.

	This behaviour seems to have occurred *after* 4.0-RELEASE.


Script started on Thu Aug  3 15:34:59 2000
: bebop; make clean all
rm -f tst so.so
c++ -g -o tst tst.cpp
c++ -g -shared -o so.so so.cpp
: bebop; gdb tst
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-unknown-freebsd"...
(gdb) set environment LD_LIBRARY_PATH .
(gdb) b dlopen
Breakpoint 1 at 0x8048814
(gdb) r so.so func
Starting program: /home/andy/tmp/bugs/c++-gdb-breakpoint/tst so.so func
Breakpoint 1 at 0x280f7c4f
Breakpoint 1 at 0x280520dd

Breakpoint 1, 0x280520dd in dlopen () from /usr/libexec/ld-elf.so.1
(gdb) fin
Run till exit from #0  0x280520dd in dlopen () from /usr/libexec/ld-elf.so.1
0x8048993 in main (argc=3, argv=0xbfbff308) at tst.cpp:14
14	    if ((h = dlopen(argv[1], RTLD_NOW)) == NULL)
(gdb) shared
Symbols already loaded for /usr/lib/libstdc++.so.3
Symbols already loaded for /usr/lib/libm.so.2
Symbols already loaded for /usr/lib/libc.so.4
Symbols already loaded for /home/andy/tmp/bugs/c++-gdb-breakpoint/./so.so
Symbols already loaded for /usr/libexec/ld-elf.so.1
(gdb) b func
Breakpoint 2 at 0x281554be: file so.cpp, line 12.
(gdb) c
Continuing.

Breakpoint 2, 0x281554be in func () at so.cpp:12
12	}                                          <==== last line of func()
(gdb) where
#0  0x281554be in func () at so.cpp:12
#1  0x8048a0d in main (argc=3, argv=0xbfbff308) at tst.cpp:18
#2  0x80488f1 in _start ()
(gdb) step
...  func() executes
main (argc=3, argv=0xbfbff308) at tst.cpp:19
19	    if (dlclose(h) == -1)
(gdb) cont

(deletia)
Script done on Thu Aug  3 15:36:13 2000


>How-To-Repeat:

	See attached shar file.  It has a simple test program that
	loads a shared object and calls a function in it.  If you
	debug this, set a break point on dlopen and "fin" from it
	so the loaded object's symbols are loaded, then set a break
	point on "func" and continue.  The break point doesn't
	occur until the function exits.


# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	so.cpp
#	tst.cpp
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
Xall: tst so.so
X
Xtst: tst.cpp
X	c++ -g -o $@ tst.cpp
X
Xso.so: so.cpp
X	c++ -g -shared -o $@ so.cpp
X
Xtest:
X	@LD_LIBRARY_PATH=`pwd` ./tst so.so func
X
Xclean:
X	rm -f tst so.so
END-of-Makefile
echo x - so.cpp
sed 's/^X//' >so.cpp << 'END-of-so.cpp'
X#include <stdio.h>
X
Xextern "C"
Xvoid
Xfunc()
X{
X    for (int i = 0; i < 10; ++i)
X	printf(".");
X    printf("In function");
X    for (int i = 0; i < 10; ++i)
X	printf(".");
X    printf("\n");
X}
END-of-so.cpp
echo x - tst.cpp
sed 's/^X//' >tst.cpp << 'END-of-tst.cpp'
X#include <stdio.h>
X#include <dlfcn.h>
X#include <err.h>
X
Xint
Xmain(int argc, char **argv)
X{
X    void	*h;
X    void	(*fn)();
X
X    if (argc != 3)
X	errx(1, "usage: %s so ident", argv[0]);
X    if ((h = dlopen(argv[1], RTLD_NOW)) == NULL)
X	errx(1, "can't dlopen %s: %s", argv[1], dlerror());
X    if ((fn = (void (*)())dlsym(h, argv[2])) == NULL)
X	errx(2, "can't dlsym %s : %s", argv[2], dlerror());
X    (*fn)();
X    if (dlclose(h) == -1)
X	errx(3, "dlclose failed: %s", dlerror());
X    return 0;
X}
END-of-tst.cpp
exit



>Fix:
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->jdp 
Responsible-Changed-By: jdp 
Responsible-Changed-When: Thu Aug 3 13:31:06 PDT 2000 
Responsible-Changed-Why:  
If the dynamic linker is broken then it is no doubt my fault. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=20373 
Responsible-Changed-From-To: jdp->obrien 
Responsible-Changed-By: jdp 
Responsible-Changed-When: Thu Aug 3 14:03:35 PDT 2000 
Responsible-Changed-Why:  
I looked into this problem and it appears to be a compiler bug, not 
a problem in the dynamic linker.  Examining the code at the 
breakpoint with the "x/i" command in gdb shows that the breakpoint 
is in fact being set at the right place.  The problem is that the 
line number information in the shared object seems to be wrong. 
It does not make any difference whether the shared object is 
loaded at runtime with dlopen or just linked into the executable. 
In either case the failure is the same. 

As a further test, I built your test case with gcc-2.7.2.3 on a 
FreeBSD 3.5-STABLE system and then tested it under -current using 
-current's dynamic linker and gdb.  That worked fine.  Yet the same 
test case when built with -current's compiler (gcc-2.95.2) failed 
just as you reported. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=20373 

From: Andy Newman <andy@silverbrook.com.au>
To: freebsd-gnats-submit@FreeBSD.org, andy@silverbrook.com.au
Cc:  
Subject: Re: bin/20373: Setting breakpoints in shared objects broken
Date: Mon, 14 Aug 2000 16:13:32 +1000

 Thanks for verifying this John.  I thought I was going crazy for a while
 (I'm working with
 a very large program that makes extensive use of run-time loading of
 shared objects. Not
 being able to debug anything is hurting.  Hmmm, so what's happened in
 stable and current
 recently with the compiler?  Binutils?
 --
 Andy Newman
 

From: Bruce Bauman <bbauman@wgate.com>
To: freebsd-gnats-submit@FreeBSD.org, andy@silverbrook.com.au
Cc:  
Subject: Re: bin/20373: Setting breakpoints in shared objects broken
Date: Fri, 08 Sep 2000 09:03:34 -0400

 <html>
 Here's some mail we received from Max Khon regarding this problem. He was
 kind enough to include a patch, which can be obtained by doing a diff of
 revisions 1.8 and 1.9 of elf32-i386.c in the CVS tree.<br>
 <br>
 Could someone please apply this patch or upgrade binutils to a more
 recent version? It makes debugging Mozilla much more pleasant :-).<br>
 <br>
 Thanks.<br>
 <br>
 hi, there!<br>
 On Thu, 7 Sep 2000, Bruce Bauman wrote:<br>
 &gt; Thanks for your prompt reply. The e-mail I received didn't include
 an <br>
 &gt; attachment. I grabbed a copy of binutils-2.10.0.24 from a mirror
 site, but <br>
 &gt; it contained many changes from the version currently in
 RELENG_4.<br>
 sorry, forgot to attach file (as usual :)<br>
 &gt; Is there a place where I can view the changes to the binutils tree
 via <br>
 &gt; cvsweb or something like that? Or is it easier for you to send us a
 patch?<br>
 <font color="#0000FF"><u><a href="http://sources.redhat.com/binutils" eudora="autourl">http://sources.redhat.com/binutils</a>/</font></u><font color="#000000">
 <br>
 you should apply patch for libbfd/elf32-i386.c (1.8 -&gt; 1.9) <br>
 I attached a patch anyway.<br>
 /fjoe<br>
 <br>
 </font><font color="#0000FF"><u>bfd.diff <br>
 <br>
 </font></u><font face="Courier New, Courier" color="#000000">--- contrib/binutils/bfd/elf32-i386.c.orig  Fri Aug 18 12:17:38 2000<br>
 +++ contrib/binutils/bfd/elf32-i386.c  Fri Aug 18 12:18:09 2000<br>
 @@ -1293,7 +1293,9 @@<br>
         &nbsp;&nbsp;&nbsp;&nbsp; sections against symbols defined externally<br>
         &nbsp;&nbsp;&nbsp;&nbsp; in shared libraries.&nbsp; We can't do anything<br>
         &nbsp;&nbsp;&nbsp;&nbsp; with them here.&nbsp; */<br>
 -       &nbsp; || (input_section-&gt;flags &amp; SEC_DEBUGGING) != 0)))<br>
 +       &nbsp; || ((input_section-&gt;flags &amp; SEC_DEBUGGING) != 0<br>
 +       &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &amp;&amp; (h-&gt;elf_link_hash_flags<br>
 +         &nbsp; &amp; ELF_LINK_HASH_DEF_DYNAMIC) != 0))))<br>
      {<br>
      &nbsp; /* In these cases, we don't need the relocation<br>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value.&nbsp; We check specially because in some<br>
 <br>
 <br>
 </font></html>
 
 
State-Changed-From-To: open->analyzed 
State-Changed-By: obrien 
State-Changed-When: Tue Sep 19 10:07:18 PDT 2000 
State-Changed-Why:  
1) GDB 4.x is not matched to Binutils 2.10.  A GDB 5.0 upgrade is in progress 
2) Binutils 2.10.0.24 is NOT, I repeat (NOT) the an offical Binutils release. 
It is a Linux-only version that exists be cause the Linux toolchain 
maintainer refuses to work properly with the Binutils developers.  This 
also explains why there are many differences between the offical 2.10 and 
this rouge version. 
3) It should have been clearly stated that "by doing a diff of revisions 1.8 
and 1.9 of elf32-i386.c in the CVS tree" refers to the Cygnus Sourceware 
anoncvs repository as there is no rev 1.9 in 
src/contrib/binutils/bfd/elf32-i386.c,v of the FreeBSD CVS repository.   
Rev 1.8 is the version in Binutils 2.10.0, rev 1.9 was committed after the 
binutils_2.10 release branch was created.  The Binutils maintainers do not 
feel there are any critical bugs in 2.10.0.  Thus they have not committed 
rev 1.9 to the binutils_2.10 release branch.  You are free to try to 
convience them that rev 1.9 should be committed to the binutils_2.10 
release branch so that it will show up in Binutils 2.10.1.  But that is a 
battle I do not wish to fight. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=20373 
Responsible-Changed-From-To: obrien->freebsd-bugs 
Responsible-Changed-By: obrien 
Responsible-Changed-When: Mon Sep 10 09:25:26 PDT 2001 
Responsible-Changed-Why:  
I am not the maintainer. 

http://www.FreeBSD.org/cgi/query-pr.cgi?pr=20373 
State-Changed-From-To: analyzed->patched 
State-Changed-By: mp 
State-Changed-When: Wed Jul 3 07:42:41 PDT 2002 
State-Changed-Why:  
This is fixed in -current with the import of gdb-5.2. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=20373 
State-Changed-From-To: patched->closed 
State-Changed-By: matteo 
State-Changed-When: Sun Jul 31 12:03:54 GMT 2005 
State-Changed-Why:  
Fixed and MFCed 

http://www.freebsd.org/cgi/query-pr.cgi?pr=20373 
>Unformatted:
