* How to call operator<< functions?
@ 2006-08-30 10:11 Michael Veksler
2006-08-30 11:13 ` Frederic RISS
2006-08-30 12:46 ` How to call operator<< functions? Daniel Jacobowitz
0 siblings, 2 replies; 23+ messages in thread
From: Michael Veksler @ 2006-08-30 10:11 UTC (permalink / raw)
To: gdb
Hello,
I have searched the web for an answer without success. The following
problem does not seem to exist. Either my configuration is broken in a
unique way or my requirements are considered weird and outrageous (so no
one tries to do similar things). Read on and tell me what you think.
I have a complex data structure MyClass (e.g. a parse tree) which I want
to examine in GDB. It is impractical to traverse and print it node by
node from GDB. For that I have written both MyClass::Print(ostream&)
and operator<< that invokes this Print. These method and operator can
print the data structure in a very nice and readable form. I can use
them to print the data into some stream when my application operates in
verbose mode.
Now I want to invoke the operator<<(ostream& , MyClass const &) function,
or alternatively the MyClass::Print(ostream&) const -- from GDB;
This does not work even with gcb-6.5, not to mention older versions. The
compiler RedHat's gcc-3.4.
Passing 'std::cout' seems impossible. Any attempt to pass std::cout
crashes. To overcome this I define my own global
ostream gecLog(cout.rdbuf());
(or something similar) and recompile the code. This lets me pass gecLog
instead of cout, and it _sometimes_ works:
(gdb) p pd.Print(gecLog)
Cannot resolve method (null)Print to any overloaded instance
-----------
Now, going through function pointers helps for some weird reason:
(gdb) p pd.Print
$13 = &MyClass::Print(std::ostream&) const
(gdb) p $13(&pd, gecLog)
Enter Print()
(gdb) p $15(&pd, std::cout)
Program received signal SIGSEGV, Segmentation fault.
0x0042cf88 in std::ostream::sentry::sentry () from /usr/lib/libstdc++.so.6
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function
(MyClass::Print(std::ostream&) const) will be abandoned.
--------------------------------------
I wanted to do the same for operator<<:
(gdb) p 'operator<<(std::ostream&, MyClass const&)'
$17 = {ostream &(ostream &, const class MyClass
&)} 0x8068a00 <operator<<(std::ostream&, MyClass const&)>
(gdb) p $17(gecLog, *pd)
Program received signal SIGSEGV, Segmentation fault.
-----------------------
Now, I wanted to write a GDB macro to call Print for me. When I try to use
p $-1(&pd, gecLog)
I get a SIGSEGV (when with p $14(....) it would "just" work).
---------------------
Is there any way to overcome any of the above problems? All I want is to
pass a stream such as cerr/cout/clog to a printing function, is that
unreasonable?
Thanks
Michael
P.S.
To overcome this, I am writing a method MyClass::DebugPrint() that calls
Print(cerr). Sometimes, while debugging a piece of code, that a vital
object has <<, but no DebugPrint, and *that* really frustrates me -
especially when I loose a 60 minutes debugging session to a SIGSEGV.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 10:11 How to call operator<< functions? Michael Veksler
@ 2006-08-30 11:13 ` Frederic RISS
2006-08-30 13:30 ` Frederic RISS
2006-08-30 12:46 ` How to call operator<< functions? Daniel Jacobowitz
1 sibling, 1 reply; 23+ messages in thread
From: Frederic RISS @ 2006-08-30 11:13 UTC (permalink / raw)
To: Michael Veksler; +Cc: gdb
On Wed, 2006-08-30 at 13:11 +0300, Michael Veksler wrote:
> Passing 'std::cout' seems impossible. Any attempt to pass std::cout
> crashes. To overcome this I define my own global
> ostream gecLog(cout.rdbuf());
> (or something similar) and recompile the code. This lets me pass gecLog
> instead of cout, and it _sometimes_ works:
Just to reply to this little part.
I've already encountered the issue with cout. In my case the _ZSt4cout
symbol was present in the debugged binary and (obviously) in libstdc++.
I _think_ that GDB resolved _ZSt4cout as if the symbol in the library
was used whereas the one in the executable was the right one. I can't
remember the reasons for this right now.
As a workaround, I passed '*(ostream*)<addr>' in place of std::cout. I
found <addr> using nm on my binary. This seemed to work if I remember
well. It's been a while though...
Hope this helps,
Fred.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 10:11 How to call operator<< functions? Michael Veksler
2006-08-30 11:13 ` Frederic RISS
@ 2006-08-30 12:46 ` Daniel Jacobowitz
2006-08-30 20:05 ` Michael Veksler
1 sibling, 1 reply; 23+ messages in thread
From: Daniel Jacobowitz @ 2006-08-30 12:46 UTC (permalink / raw)
To: Michael Veksler; +Cc: gdb
As a general note: the most useful thing to accompany any bug report is
a test case! :-) We can't fix them without tests.
On Wed, Aug 30, 2006 at 01:11:43PM +0300, Michael Veksler wrote:
> Passing 'std::cout' seems impossible. Any attempt to pass std::cout
> crashes. To overcome this I define my own global
> ostream gecLog(cout.rdbuf());
> (or something similar) and recompile the code. This lets me pass gecLog
> instead of cout, and it _sometimes_ works:
Fred's response seems reasonable; that might be the problem, or it
might be something else. If you have a testcase, please post it.
> (gdb) p pd.Print(gecLog)
> Cannot resolve method (null)Print to any overloaded instance
Ditto. I've never seen this error before.
> --------------------------------------
> I wanted to do the same for operator<<:
> (gdb) p 'operator<<(std::ostream&, MyClass const&)'
> $17 = {ostream &(ostream &, const class MyClass
> &)} 0x8068a00 <operator<<(std::ostream&, MyClass const&)>
> (gdb) p $17(gecLog, *pd)
> Program received signal SIGSEGV, Segmentation fault.
> -----------------------
You can just use "print gecLog << *pd". Does that work better?
Anyway, I would have expected calling the operator to work.
With tests for these bugs we can make the next GDB release the
best ever for C++.
> Print(cerr). Sometimes, while debugging a piece of code, that a vital
> object has <<, but no DebugPrint, and *that* really frustrates me -
> especially when I loose a 60 minutes debugging session to a SIGSEGV.
You might want to use set unwindonsignal, then, as it suggests.
There's some risk associated, but it usually works. You can also
use "return" to get out of the called function, but make sure you tell
GDB not to pass the sigsegv when you continue.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 11:13 ` Frederic RISS
@ 2006-08-30 13:30 ` Frederic RISS
2006-08-30 13:40 ` Breakpoint Handling in GDB Veenu Verma (AS/EAB)
2006-08-31 11:34 ` Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?) Frederic RISS
0 siblings, 2 replies; 23+ messages in thread
From: Frederic RISS @ 2006-08-30 13:30 UTC (permalink / raw)
To: gdb
On Wed, 2006-08-30 at 13:12 +0200, Frederic RISS wrote:
> I've already encountered the issue with cout. In my case the _ZSt4cout
> symbol was present in the debugged binary and (obviously) in libstdc++.
> I _think_ that GDB resolved _ZSt4cout as if the symbol in the library
> was used whereas the one in the executable was the right one. I can't
> remember the reasons for this right now.
I digged an old testcase out. Very simple:
-----------------------------8<-----------------------------------
#include <iostream>
void dump (std::ostream& os)
{
os << "Hello, guys!" << std::endl;
}
int main ()
{
std::cout << "&std::cout is " << &std::cout << std::endl;
dump (std::cout);
return 0;
}
-----------------------------8<-----------------------------------
With neither of the toolcahins I tried (all x86, gcc 4.0 and 4.1 with
recent binutils) I could get the correct value for &std::cout:
rf23@crx549 ~/tmp/cout % gdb --silent a.out
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) start
Breakpoint 1 at 0x8048703: file cout.cc, line 11.
Starting program: /home/rf23/tmp/cout/a.out
main () at cout.cc:11
11 std::cout << "&std::cout is " << &std::cout << std::endl;
(gdb) n
&std::cout is 0x8049a78
12 dump (std::cout);
(gdb) p &std::cout
$1 = (ostream *) 0x582b40
p dump (std::cout)
Program received signal SIGSEGV, Segmentation fault.
As you can see, we get the wrong address. Thus we fail to pass the right
object when calling a function. Little (re-)investigation showed that
this is related to symbol versionning. In the static symtab the
std::cout symbol is versioned and is recorded as such in GDB's minsym
table:
rf23@crx549 ~/tmp/cout % nm a.out| grep cout
49:08049a78 B _ZSt4cout@@GLIBCXX_3.4
rf23@crx549 ~/tmp/cout % nm -D a.out| grep cout
11:08049a78 B _ZSt4cout
This can be confirmed from within GDB:
(gdb) p &'_ZSt4cout@@GLIBCXX_3.4'
$2 = (<data variable, no debug info> *) 0x8049a78
I don't know how we should handle that. Trimming the symbol versions
seems wrong (and scanning each symbol for @@ has a cost). Maybe we
shouldn't skip the dynamic symtab for the main executable? Not sure if
it'll solve all such cases.
Fred.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Breakpoint Handling in GDB
2006-08-30 13:30 ` Frederic RISS
@ 2006-08-30 13:40 ` Veenu Verma (AS/EAB)
2006-08-30 13:43 ` Daniel Jacobowitz
2006-08-30 20:30 ` Michael Snyder
2006-08-31 11:34 ` Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?) Frederic RISS
1 sibling, 2 replies; 23+ messages in thread
From: Veenu Verma (AS/EAB) @ 2006-08-30 13:40 UTC (permalink / raw)
To: gdb
Hello
I was going through the gdb internals on software breakpoint handling
and have a question regarding that.
Gdb replaces the program instruction with a trap which means target does
not have any control over setting a bp.
What happens if the connection with the gdb breaks down ?
Does it mean that the illegal instruction won't be restored and the
application will crash ?
If that's the case, then how can it be handled ?
Thanx
Veenu
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Breakpoint Handling in GDB
2006-08-30 13:40 ` Breakpoint Handling in GDB Veenu Verma (AS/EAB)
@ 2006-08-30 13:43 ` Daniel Jacobowitz
2006-08-30 20:30 ` Michael Snyder
1 sibling, 0 replies; 23+ messages in thread
From: Daniel Jacobowitz @ 2006-08-30 13:43 UTC (permalink / raw)
To: Veenu Verma (AS/EAB); +Cc: gdb
On Wed, Aug 30, 2006 at 03:40:21PM +0200, Veenu Verma (AS/EAB) wrote:
> Hello
> I was going through the gdb internals on software breakpoint handling
> and have a question regarding that.
> Gdb replaces the program instruction with a trap which means target does
> not have any control over setting a bp.
> What happens if the connection with the gdb breaks down ?
> Does it mean that the illegal instruction won't be restored and the
> application will crash ?
> If that's the case, then how can it be handled ?
Implement the z0/Z0 packets in your stub instead, and then GDB will use
them.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 12:46 ` How to call operator<< functions? Daniel Jacobowitz
@ 2006-08-30 20:05 ` Michael Veksler
2006-08-30 20:24 ` Daniel Jacobowitz
0 siblings, 1 reply; 23+ messages in thread
From: Michael Veksler @ 2006-08-30 20:05 UTC (permalink / raw)
To: Michael Veksler, gdb
Daniel Jacobowitz wrote:
> As a general note: the most useful thing to accompany any bug report is
> a test case! :-) We can't fix them without tests.
>
You are right. At the end of this mail there is a complete test case for
about 50% of the reported problems. I'll have to work harder for a
simple test case for the other 50%.
> On Wed, Aug 30, 2006 at 01:11:43PM +0300, Michael Veksler wrote:
>
>> I wanted to do the same for operator<<:
>> (gdb) p 'operator<<(std::ostream&, MyClass const&)'
>> $17 = {ostream &(ostream &, const class MyClass
>> &)} 0x8068a00 <operator<<(std::ostream&, MyClass const&)>
>> (gdb) p $17(gecLog, *pd)
>> Program received signal SIGSEGV, Segmentation fault.
>>
> You can just use "print gecLog << *pd". Does that work better?
> Anyway, I would have expected calling the operator to work.
>
>
Does not work, look at my complete report below.
> With tests for these bugs we can make the next GDB release the
> best ever for C++.
>
Would be great.
>> Print(cerr). Sometimes, while debugging a piece of code, that a vital
>> object has <<, but no DebugPrint, and *that* really frustrates me -
>> especially when I loose a 60 minutes debugging session to a SIGSEGV.
>>
>
> You might want to use set unwindonsignal, then, as it suggests.
> There's some risk associated, but it usually works. You can also
> use "return" to get out of the called function, but make sure you tell
> GDB not to pass the sigsegv when you continue.
>
>
Thanks this might help 95% of the time.
In some cases I get std::bad_alloc uncaught exception during Print
(again, when it should have worked). I doubt that these 5% of crashes
can be recovered from. Not a big deal, as it is only about 5..10%.
The complete test case is comprised of c++ source file (compiled with
RHEL4's gcc-3.4 using "g++ -g "), and of screen trace.
Should I open a PR, or several PRs?
Maybe someone else that can split my single test case into subtopics,
each to fit its own PR?
Does it make sense to create test case for the missing 50% of the
crashes I have seen, or will it be better to wait and see if they get
fixed by other PRs?
===================
=> cat cout-gdb.cpp
#include <iostream>
using namespace std;
ostream myCout(cout.rdbuf());
struct A
{
virtual void Print(ostream &out) const = 0;
};
struct B : public A
{
virtual void Print(ostream &out) const
{ out << "Enter B::Print() this=" << this << endl; }
};
ostream & operator<<(ostream & out, const A& data)
{
data.Print(out);
}
int main()
{
B x;
const A & ref_x = x;
ref_x.Print(myCout);
return 0;
}
=> gdb-6.5 -silent a.out
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b 27
Breakpoint 1 at 0x8048a26: file cout-gdb.cpp, line 27.
(gdb) r
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00
Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p x.Print(myCout)
Program received signal SIGSEGV, Segmentation fault.
0x0042cf88 in std::ostream::sentry::sentry () from /usr/lib/libstdc++.so.6
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function
(B::Print(std::ostream&) const) will be abandoned.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00
Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p ref_x.Print(myCout)
Program received signal SIGSEGV, Segmentation fault.
0x0042cf88 in std::ostream::sentry::sentry () from /usr/lib/libstdc++.so.6
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function
(B::Print(std::ostream&) const) will be abandoned.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00
Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p ref_x.Print
Cannot take address of method Print.
(gdb) p x.Print
$1 = &B::Print(std::ostream&) const
(gdb) p $1(&x, myCout)
Enter B::Print() this=0xbfffec00
$2 = void
(gdb) set $a=x.Print
(gdb) p $a(&x, myCout)
Program received signal SIGSEGV, Segmentation fault.
0x08527e78 in ?? ()
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (at 0x8527e78) will
be abandoned.
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00
Breakpoint 1, main () at cout-gdb.cpp:27
27 return 0;
(gdb) p myCout << x
Structure has no component named operator<<.
(gdb) p 'operator<<(std::ostream&, A const&)' (myCout, x)
Enter B::Print() this=0xbfffec00
$3 = (ostream &) @0x8049260: <incomplete type>
<<<<<< The above sometimes won't work (will be reproduced later) >>>>
(gdb) p &'_ZSt4cout@@GLIBCXX_3.4'
$4 = (<data variable, no debug info> *) 0x8049160
(gdb) p &std::cout
$5 = (ostream *) 0x47cfc0
(gdb) p x.Print
$6 = &B::Print(std::ostream&) const
(gdb) p $6(&x, '_ZSt4cout@@GLIBCXX_3.4')
Enter B::Print() this=0xbfffec00
$7 = void
(gdb) p $6(&x, std::cout)
Program received signal SIGSEGV, Segmentation fault.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 20:05 ` Michael Veksler
@ 2006-08-30 20:24 ` Daniel Jacobowitz
2006-08-30 20:45 ` Michael Veksler
0 siblings, 1 reply; 23+ messages in thread
From: Daniel Jacobowitz @ 2006-08-30 20:24 UTC (permalink / raw)
To: Michael Veksler; +Cc: gdb
On Wed, Aug 30, 2006 at 11:05:43PM +0300, Michael Veksler wrote:
> Should I open a PR, or several PRs?
> Maybe someone else that can split my single test case into subtopics,
> each to fit its own PR?
> Does it make sense to create test case for the missing 50% of the
> crashes I have seen, or will it be better to wait and see if they get
> fixed by other PRs?
Let's look at one thing at a time.
The first two crashes should, I think, be addressed by this patch.
Could you try it?
Some of the later crashes are caused by this:
(gdb) set $a = x.Print
(gdb) p $a
$7 = <error reading variable>
I have a whole lot of patches related to member functions, that I
haven't had time to merge yet - and I would not like to look at this
until I've done that.
--
Daniel Jacobowitz
CodeSourcery
2006-08-30 Daniel Jacobowitz <dan@codesourcery.com>
* infcall.c (call_function_by_hand): Check for function pointer
types.
Index: src/gdb/infcall.c
===================================================================
--- src.orig/gdb/infcall.c 2006-08-30 16:19:00.000000000 -0400
+++ src/gdb/infcall.c 2006-08-30 16:18:43.000000000 -0400
@@ -337,6 +337,9 @@ call_function_by_hand (struct value *fun
struct cleanup *caller_regcache_cleanup;
struct frame_id dummy_id;
+ if (TYPE_CODE (ftype) == TYPE_CODE_PTR)
+ ftype = check_typedef (TYPE_TARGET_TYPE (ftype));
+
if (!target_has_execution)
noprocess ();
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Breakpoint Handling in GDB
2006-08-30 13:40 ` Breakpoint Handling in GDB Veenu Verma (AS/EAB)
2006-08-30 13:43 ` Daniel Jacobowitz
@ 2006-08-30 20:30 ` Michael Snyder
1 sibling, 0 replies; 23+ messages in thread
From: Michael Snyder @ 2006-08-30 20:30 UTC (permalink / raw)
To: Veenu Verma (AS/EAB); +Cc: gdb
On Wed, 2006-08-30 at 15:40 +0200, Veenu Verma (AS/EAB) wrote:
> Hello
> I was going through the gdb internals on software breakpoint handling
> and have a question regarding that.
> Gdb replaces the program instruction with a trap which means target does
> not have any control over setting a bp.
> What happens if the connection with the gdb breaks down ?
> Does it mean that the illegal instruction won't be restored and the
> application will crash ?
In the general case, yes, that's what it means.
> If that's the case, then how can it be handled ?
The newer z0/Z0 remote commands will allow the target debug agent
(eg. gdbserver) to handle the breakpoints. But if you're using the
original method of breakpointing by writing trap instructions into
target memory, then yes, you're vulnerable to the scenario that you
describe.
If you can't reboot the target, you MIGHT try re-connecting with
gdb, and "fixing" the trap instructions by hand. Obviously this
is "at your own risk". GDB does not have any built-in capability
to help with the situation that you describe.
However, I *have* used the following method:
1) If possible, get the locations of the breakpoints using
gdb's "info break" command.
2) WITHOUT reconnecting to the target, load the target's
executable file into gdb, and examine (and record) the contents
of memory at those locations, eg. like this:
(gdb) print /x *(unsigned int *) 0xabcdef
3) Now reconnect to the target, and modify those locations
to match what's in the original binary file, eg.:
(gdb) set *(unsigned int *) 0xabcdef = <value>
Again, YMMV, use at your own risk, operators are trained
professionals etc. etc.
Remember, there may be trap instructions that you don't know about,
eg. if you were in the middle of a "next" or "finish" when you lost
communication with the target.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 20:24 ` Daniel Jacobowitz
@ 2006-08-30 20:45 ` Michael Veksler
2006-08-30 20:54 ` Daniel Jacobowitz
0 siblings, 1 reply; 23+ messages in thread
From: Michael Veksler @ 2006-08-30 20:45 UTC (permalink / raw)
To: Michael Veksler, gdb
Daniel Jacobowitz wrote:
> On Wed, Aug 30, 2006 at 11:05:43PM +0300, Michael Veksler wrote:
>
> Let's look at one thing at a time.
>
> The first two crashes should, I think, be addressed by this patch.
> Could you try it?
>
With the patch it works:
(gdb) p x.Print(myCout)
Enter B::Print() this=0xbfffec00
$1 = void
(gdb) p ref_x.Print(myCout)
Enter B::Print() this=0xbfffec00
$2 = void
Great progress. The most annoying and common failures I have used to be
seeing is no more.
The other annoying issues sorted by decreasing annoyance :
- this->Print is not always found (I'll try to create a small test-case
later).
- std::cout related crashes
- print myCout << x --- won't work need to resort to
print 'operator<<........'(myCout, x)
> Some of the later crashes are caused by this:
>
> (gdb) set $a = x.Print
> (gdb) p $a
> $7 = <error reading variable>
>
> I have a whole lot of patches related to member functions, that I
> haven't had time to merge yet - and I would not like to look at this
> until I've done that.
>
>
This is less critical since this was an attempt to overcome the other bug.
Thanks,
Michael
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 20:45 ` Michael Veksler
@ 2006-08-30 20:54 ` Daniel Jacobowitz
2006-08-31 12:05 ` Michael Veksler
0 siblings, 1 reply; 23+ messages in thread
From: Daniel Jacobowitz @ 2006-08-30 20:54 UTC (permalink / raw)
To: Michael Veksler; +Cc: gdb
On Wed, Aug 30, 2006 at 11:45:33PM +0300, Michael Veksler wrote:
> Great progress. The most annoying and common failures I have used to be
> seeing is no more.
I will test and commit the patch (but not right this moment).
> The other annoying issues sorted by decreasing annoyance :
> - this->Print is not always found (I'll try to create a small test-case
> later).
I think my other changes will help here, though I'm not sure.
> - std::cout related crashes
Fred's pegged this one I suspect. This is a serious bug and we need to
fix it, but it will be a bit tricky.
> - print myCout << x --- won't work need to resort to
> print 'operator<<........'(myCout, x)
I think that foo::operator<< is supported, but operator<<(foo&,...)
isn't. Or else something's wrong with the support.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 23+ messages in thread
* Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-30 13:30 ` Frederic RISS
2006-08-30 13:40 ` Breakpoint Handling in GDB Veenu Verma (AS/EAB)
@ 2006-08-31 11:34 ` Frederic RISS
2006-08-31 12:09 ` Michael Veksler
1 sibling, 1 reply; 23+ messages in thread
From: Frederic RISS @ 2006-08-31 11:34 UTC (permalink / raw)
To: gdb; +Cc: GDB Patches
[-- Attachment #1: Type: text/plain, Size: 1159 bytes --]
On Linux, versioned ELF symbols are stored in the static symtab with an
(@)@VERSION suffix. We store such symbols with the suffix and thus fail
to find them when looking up the real name.
This causes failures such as the one described here:
http://www.sourceware.org/ml/gdb/2006-08/msg00244.html
In the general case, GDB doesn't use the dynamic symtab because it
contains usually only a subset of the static table information. The
attached patch make GDB store dynamic versioned symbols.
Maybe this is harvests too much symbols, and we should limit it to the
dynamic symbols of the main executable. It's easy enough to do, we just
need to pass the 'mainline' flag to elf_symfile_read from
elf_symtab_read.
I've no idea if this could break something on non-Linux platforms, I've
just tested on x86-linux.
I'm also attaching a little testsuite patch that fails for me on current
GDB and works with the patch.
Opinions?
2006-08-31 Frederic Riss <frederic.riss@st.com>
* elfread.c (elf_symtab_read): Read versioned symbols from
the dynamic symtab.
2006-08-31 Frederic Riss <frederic.riss@st.com>
* gdb.cp/userdef.exp: Test use of std::cout.
[-- Attachment #2: versioned-symbols.patch --]
[-- Type: text/x-patch, Size: 993 bytes --]
Index: elfread.c
===================================================================
RCS file: /cvs/src/src/gdb/elfread.c,v
retrieving revision 1.55
diff -u -p -r1.55 elfread.c
--- elfread.c 21 Feb 2006 20:38:48 -0000 1.55
+++ elfread.c 31 Aug 2006 10:50:17 -0000
@@ -211,9 +211,14 @@ elf_symtab_read (struct objfile *objfile
/* If it is a nonstripped executable, do not enter dynamic
symbols, as the dynamic symbol table is usually a subset
- of the main symbol table. */
- if (dynamic && !stripped)
+ of the main symbol table.
+ The Linux ELF symbol versionning requires that the versioned
+ static symbols are suffixed with (@)@VERSION, thus the
+ entries we got from the static symtab for these symbols have
+ suffixed names. The entries in the dynamic symtab don't have
+ the suffix (version info is stored in .gnu_version section). */
+ if (dynamic && !stripped && !((elf_symbol_type *) sym)->version)
continue;
if (sym->flags & BSF_FILE)
{
[-- Attachment #3: testsuite-cout.patch --]
[-- Type: text/x-patch, Size: 719 bytes --]
? testsuite-cout.patch
Index: gdb.cp/userdef.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.cp/userdef.exp,v
retrieving revision 1.6
diff -u -p -r1.6 userdef.exp
--- gdb.cp/userdef.exp 10 Aug 2006 05:27:20 -0000 1.6
+++ gdb.cp/userdef.exp 31 Aug 2006 10:58:01 -0000
@@ -151,5 +151,8 @@ gdb_test "print *c" "\\\$\[0-9\]* = \\(M
gdb_test "print &*c" "\\\$\[0-9\]* = \\(Member \\*\\) $hex"
gdb_test "ptype &*c" "type = struct Member {\[\r\n \]+int z;\[\r\n\]+} &\\*"
+# Check that we're able to use std::cout
+gdb_test "print 'operator<<'(std::cout, one)" "\[\r\n\]+x = 9\[\r\n\]+y = 10\[\r\n\]+-------\[\r\n\]+\\\$\[0-9\]* = .*"
+
gdb_exit
return 0
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: How to call operator<< functions?
2006-08-30 20:54 ` Daniel Jacobowitz
@ 2006-08-31 12:05 ` Michael Veksler
0 siblings, 0 replies; 23+ messages in thread
From: Michael Veksler @ 2006-08-31 12:05 UTC (permalink / raw)
To: Michael Veksler, gdb
Daniel Jacobowitz wrote:
> On Wed, Aug 30, 2006 at 11:45:33PM +0300, Michael Veksler wrote:
>> Great progress. The most annoying and common failures I have used to
>> be seeing is no more.
>
> I will test and commit the patch (but not right this moment).
>
No hurry, I have managed for eight years, I can cope with it a bit more.
>> The other annoying issues sorted by decreasing annoyance :
>> - this->Print is not always found (I'll try to create a small
>> test-case later).
>
> I think my other changes will help here, though I'm not sure.
I doubt they will. I have produced a complete test case for that. See
below.
>> - std::cout related crashes
>
> Fred's pegged this one I suspect. This is a serious bug and we need to
> fix it, but it will be a bit tricky.
My following test case may be related to this.
>> - print myCout << x --- won't work need to resort to
>> print 'operator<<........'(myCout, x)
>
> I think that foo::operator<< is supported, but operator<<(foo&,...)
> isn't. Or else something's wrong with the support.
Well, it works without the std:: as the prefix of operator<<.
I hoped that just using << (as in C++) would just work.
==========
Here is the test case.
=> cat cout-gdb2.cpp
#include <iostream>
using namespace std;
extern int forceLink;
struct A
{
virtual void Print(ostream &out) const = 0;
};
struct B : public A
{
virtual void Print(ostream &out) const ;
};
void B::Print(ostream &out) const
{
out << "Enter B::Print() this=" << this << endl;
}
ostream & operator<<(ostream & out, const A& data)
{
data.Print(out);
}
int main()
{
B x;
const A & ref_x = x;
ref_x.Print(cout);
return forceLink;
}
=> cat myCout.cpp
#include <iostream>
using namespace std;
ostream myCout(cout.rdbuf());
// A trick to force the linker put this object file into the executable
int forceLink=0;
=> g++ -g cout-gdb.cpp myCout.cpp
=> gdb-6.5 -silent a.out
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b 30
Breakpoint 1 at 0x8048a62: file cout-gdb.cpp, line 30.
(gdb) r
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00
Breakpoint 1, main () at cout-gdb.cpp:30
30 return forceLink;
(gdb) p myCout
$1 = <incomplete type>
(gdb) p x.Print(myCout)
Cannot resolve method B::Print to any overloaded instance
(gdb) p x.Print
$2 = &B::Print(std::ostream&) const
(gdb) p $2(&x, myCout)
Enter B::Print() this=0xbfffec00
$3 = void
(gdb)
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 11:34 ` Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?) Frederic RISS
@ 2006-08-31 12:09 ` Michael Veksler
2006-08-31 12:26 ` Frederic RISS
0 siblings, 1 reply; 23+ messages in thread
From: Michael Veksler @ 2006-08-31 12:09 UTC (permalink / raw)
To: Frederic RISS; +Cc: gdb, GDB Patches
Frederic RISS wrote:
> On Linux, versioned ELF symbols are stored in the static symtab with an
> (@)@VERSION suffix. We store such symbols with the suffix and thus fail
> to find them when looking up the real name.
>
> This causes failures such as the one described here:
> http://www.sourceware.org/ml/gdb/2006-08/msg00244.html
>
> In the general case, GDB doesn't use the dynamic symtab because it
> contains usually only a subset of the static table information. The
> attached patch make GDB store dynamic versioned symbols.
>
> Maybe this is harvests too much symbols, and we should limit it to the
> dynamic symbols of the main executable. It's easy enough to do, we just
> need to pass the 'mainline' flag to elf_symfile_read from
> elf_symtab_read.
>
> I've no idea if this could break something on non-Linux platforms, I've
> just tested on x86-linux.
>
> I'm also attaching a little testsuite patch that fails for me on current
> GDB and works with the patch.
>
> Opinions?
>
Great, now std::cout does not cause crashes. Still there is the problem of
(gdb) p std::cout
$1 = <incomplete type>
But that's unrelated, right?
The problem with this result is that it sometimes confuses GDB as
described at the end of:
http://sources.redhat.com/ml/gdb/2006-08/msg00271.html
Michael
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 12:09 ` Michael Veksler
@ 2006-08-31 12:26 ` Frederic RISS
2006-08-31 13:02 ` Michael Veksler
0 siblings, 1 reply; 23+ messages in thread
From: Frederic RISS @ 2006-08-31 12:26 UTC (permalink / raw)
To: Michael Veksler; +Cc: gdb
On Thu, 2006-08-31 at 15:09 +0300, Michael Veksler wrote:
> Great, now std::cout does not cause crashes. Still there is the problem of
>
> (gdb) p std::cout
> $1 = <incomplete type>
>
> But that's unrelated, right?
Yes, unrelated.
This should work if you've got a version of libstdc++ compiled with
debug info. If you don't, then GDB can't find std::cout's type. This
works for me once the library is loaded (i.e. once the inferior is
running):
(gdb) p std::cout
$1 = <incomplete type>
(gdb) ptype std::cout
type = struct std::basic_ostream<char,std::char_traits<char> > {
<incomplete type>
}
(gdb) start
Breakpoint 1 at 0x8048703: file cout.cc, line 11.
Starting program: /home/rf23/tmp/cout/a.out
main () at cout.cc:11
11 std::cout << "&std::cout is " << &std::cout << std::endl;
(gdb) ptype std::cout
type = class std::basic_ostream<char,std::char_traits<char> >
: public virtual std::basic_ios<char,std::char_traits<char> > {
public:
void basic_ostream(int, const void **,
class std::basic_streambuf<char,std::char_traits<char> > *);
protected:
void basic_ostream(int, const void **);
public:
~basic_ostream(int, const void **);
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(std::ostream& (*)(std::ostream&));
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(std::basic_ios<char, std::char_traits<char> >& (*)(std::basic_ios<char, std::char_traits<char> >&));
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(std::ios_base& (*)(std::ios_base&));
class std::basic_ostream<char,std::char_traits<char> > & operator<<(long);
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(unsigned long);
class std::basic_ostream<char,std::char_traits<char> > & operator<<(bool);
class std::basic_ostream<char,std::char_traits<char> > & operator<<(short);
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(unsigned short);
class std::basic_ostream<char,std::char_traits<char> > & operator<<(int);
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(unsigned int);
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(long long);
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(unsigned long long);
class std::basic_ostream<char,std::char_traits<char> >
& operator<<(double);
class std::basic_ostream<char,std::char_traits<char> > & operator<<(float);
class std::basic_ostream<char,std::char_traits<char> >
---Type <return> to continue, or q <return> to quit---q
& operator<<(long douQuit
(gdb) q
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 12:26 ` Frederic RISS
@ 2006-08-31 13:02 ` Michael Veksler
2006-08-31 13:23 ` Frederic RISS
0 siblings, 1 reply; 23+ messages in thread
From: Michael Veksler @ 2006-08-31 13:02 UTC (permalink / raw)
To: Frederic RISS; +Cc: gdb
Frederic RISS wrote:
> On Thu, 2006-08-31 at 15:09 +0300, Michael Veksler wrote:
>
>
>> Great, now std::cout does not cause crashes. Still there is the problem of
>>
>> (gdb) p std::cout
>> $1 = <incomplete type>
>>
>> But that's unrelated, right?
>>
>
> Yes, unrelated.
> This should work if you've got a version of libstdc++ compiled with
> debug info. If you don't, then GDB can't find std::cout's type. This
> works for me once the library is loaded (i.e. once the inferior is
> running):
>
>
Sounds reasonable, however look at the end for my test.
> (gdb) ptype std::cout
> type = struct std::basic_ostream<char,std::char_traits<char> > {
> <incomplete type>
> }
> (gdb) start
>
...
> (gdb) ptype std::cout
> type = class std::basic_ostream<char,std::char_traits<char> >
> : public virtual std::basic_ios<char,std::char_traits<char> > {
>
Take the two files from my test case in:
http://sources.redhat.com/ml/gdb/2006-08/msg00271.html
=> gdb-6.5 -silent a.out
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) b 30
Breakpoint 1 at 0x8048a62: file cout-gdb.cpp, line 30.
(gdb) r
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00
Breakpoint 1, main () at cout-gdb.cpp:30
warning: Source file is more recent than executable.
30 return forceLink;
(gdb) p x.Print(std::cout)
Enter B::Print() this=0xbfffec00
$1 = void
(gdb) p x.Print(myCout)
Cannot resolve method B::Print to any overloaded instance
(gdb) p x.Print(std::cout)
Cannot resolve method B::Print to any overloaded instance
(gdb)
==============
What is going on here. Why the second Print(std::cout) no longer works?
Let's try to rerun without exiting GDB:
=============
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/veksler/a.out
Enter B::Print() this=0xbfffec00
Breakpoint 1, main () at cout-gdb.cpp:30
30 return forceLink;
(gdb) p x.Print(std::cout)
Cannot resolve method B::Print to any overloaded instance
(gdb)
===========
Still does not work!?
Is it related to your patch?
Michael
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 13:02 ` Michael Veksler
@ 2006-08-31 13:23 ` Frederic RISS
2006-08-31 16:48 ` Frederic RISS
0 siblings, 1 reply; 23+ messages in thread
From: Frederic RISS @ 2006-08-31 13:23 UTC (permalink / raw)
To: Michael Veksler; +Cc: gdb
On Thu, 2006-08-31 at 16:02 +0300, Michael Veksler wrote:
> Take the two files from my test case in:
> http://sources.redhat.com/ml/gdb/2006-08/msg00271.html
> [...]
> (gdb) p x.Print(std::cout)
> Enter B::Print() this=0xbfffec00
> $1 = void
> (gdb) p x.Print(myCout)
> Cannot resolve method B::Print to any overloaded instance
> (gdb) p x.Print(std::cout)
> Cannot resolve method B::Print to any overloaded instance
> (gdb)
> ==============
> What is going on here. Why the second Print(std::cout) no longer works?
> Let's try to rerun without exiting GDB:
Sorry, I can't reproduce that... this is working fine here.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 13:23 ` Frederic RISS
@ 2006-08-31 16:48 ` Frederic RISS
2006-08-31 16:57 ` Daniel Jacobowitz
0 siblings, 1 reply; 23+ messages in thread
From: Frederic RISS @ 2006-08-31 16:48 UTC (permalink / raw)
To: Michael Veksler; +Cc: gdb
On Thu, 2006-08-31 at 15:23 +0200, Frederic RISS wrote:
> On Thu, 2006-08-31 at 16:02 +0300, Michael Veksler wrote:
> > Take the two files from my test case in:
> > http://sources.redhat.com/ml/gdb/2006-08/msg00271.html
> > [...]
> > (gdb) p x.Print(std::cout)
> > Enter B::Print() this=0xbfffec00
> > $1 = void
> > (gdb) p x.Print(myCout)
> > Cannot resolve method B::Print to any overloaded instance
> > (gdb) p x.Print(std::cout)
> > Cannot resolve method B::Print to any overloaded instance
> > (gdb)
> > ==============
> > What is going on here. Why the second Print(std::cout) no longer works?
> > Let's try to rerun without exiting GDB:
>
> Sorry, I can't reproduce that... this is working fine here.
In fact I managed to reproduce this behavour using a libstdc++ compiled
without debug information. What's happening is quite strange, and it
might very well be a GCC bug and not a GDB one.
What happens is that you get 2 definitions of std::cout in the debug
information of your example. One definition for each file. The gotcha is
that neither of these definitions are complete. They're just empty
shells specifying that the symbol is of type
``typedef basic_ostream<char,std::char_traits<char> > std::ostream''
without giving a clue to the debugger what this type is made of.
I think GCC should emit a complete type because you use std::ostream in
each of your files.
The first 'p x.Print(std::cout)' works because at this point, the
debugger has only read the full debug information of the first file.
This file contains a definition of std::cout and the definition of
B::Print which both point to the same instance of the std::ostream type.
Being the same instance, even if the type is incomplete GDB resolves the
overload correctly.
After you've referenced 'myCout' which is defined in the second file,
the debug info of the latter has been read, bringing a second definition
of std::cout in the global scope. This second definition is found by
further lookups of this symbol, and this time, the symbol type isn't the
same instance as before. GDB tries to compare to incomplete types and of
course it fails...
I thought that using -feliminate-dwarf2-dups would help, but it doesn't.
One thing we could do is to compare the TYPE_TAG_NAME for overload
resoltion if there's no type name. During my tests, it was set to
'std::basic_ostream<char,std::char_traits<char> >' but I've read some
comments stating that it shouldn't be used. Or maybe the bug is that we
don't fill TYPE_NAME with that information?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 16:48 ` Frederic RISS
@ 2006-08-31 16:57 ` Daniel Jacobowitz
2006-08-31 17:41 ` Frédéric Riss
2006-08-31 19:48 ` Michael Veksler
0 siblings, 2 replies; 23+ messages in thread
From: Daniel Jacobowitz @ 2006-08-31 16:57 UTC (permalink / raw)
To: Frederic RISS; +Cc: Michael Veksler, gdb
On Thu, Aug 31, 2006 at 06:48:04PM +0200, Frederic RISS wrote:
> What happens is that you get 2 definitions of std::cout in the debug
> information of your example. One definition for each file. The gotcha is
> that neither of these definitions are complete. They're just empty
> shells specifying that the symbol is of type
> ``typedef basic_ostream<char,std::char_traits<char> > std::ostream''
> without giving a clue to the debugger what this type is made of.
> I think GCC should emit a complete type because you use std::ostream in
> each of your files.
This is a deliberate choice on GCC's part, to reduce overly excessive
debug information. There've been arguments about it in the past. My
feeling is that we will end up with something like a -gfull argument
to force the extra information to be emitted. GDB needs to work as
well as possible anyway.
> The first 'p x.Print(std::cout)' works because at this point, the
> debugger has only read the full debug information of the first file.
> This file contains a definition of std::cout and the definition of
> B::Print which both point to the same instance of the std::ostream type.
> Being the same instance, even if the type is incomplete GDB resolves the
> overload correctly.
> After you've referenced 'myCout' which is defined in the second file,
> the debug info of the latter has been read, bringing a second definition
> of std::cout in the global scope. This second definition is found by
> further lookups of this symbol, and this time, the symbol type isn't the
> same instance as before. GDB tries to compare to incomplete types and of
> course it fails...
This is a problem with GDB, that I've always been amazed we didn't
hit more often. It's a very difficult problem and I don't really know
what we should be doing about it. I don't know if there's a standard
term for this, but I've called it type unification in the past.
We need some way to figure out that these are the same type, to the
best of our knowledge.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 16:57 ` Daniel Jacobowitz
@ 2006-08-31 17:41 ` Frédéric Riss
2006-08-31 17:45 ` Daniel Jacobowitz
2006-08-31 19:48 ` Michael Veksler
1 sibling, 1 reply; 23+ messages in thread
From: Frédéric Riss @ 2006-08-31 17:41 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Frederic RISS, Michael Veksler, gdb
Le jeudi 31 août 2006 à 12:57 -0400, Daniel Jacobowitz a écrit :
> > GDB tries to compare to incomplete types and of
> > course it fails...
>
> This is a problem with GDB, that I've always been amazed we didn't
> hit more often. It's a very difficult problem and I don't really know
> what we should be doing about it. I don't know if there's a standard
> term for this, but I've called it type unification in the past.
>
> We need some way to figure out that these are the same type, to the
> best of our knowledge.
In the case of C++ classes (not POD objects, but classes with methods),
the One Definition Rule gives us a way to identify those, doesn't it? I
mean both classes are named basic_ostream<char,std::char_traits<char> >
and live in the std namespace. All this is clearly described by the
Dwarf tree structure.
Of course in this case, we're speaking about incomplete types here, and
we don't know they're really not simple structures. Thus applying this
unification logic would is a bit dangerous.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 17:41 ` Frédéric Riss
@ 2006-08-31 17:45 ` Daniel Jacobowitz
0 siblings, 0 replies; 23+ messages in thread
From: Daniel Jacobowitz @ 2006-08-31 17:45 UTC (permalink / raw)
To: Frédéric Riss; +Cc: Frederic RISS, Michael Veksler, gdb
On Thu, Aug 31, 2006 at 07:41:20PM +0200, Frédéric Riss wrote:
> In the case of C++ classes (not POD objects, but classes with methods),
> the One Definition Rule gives us a way to identify those, doesn't it? I
> mean both classes are named basic_ostream<char,std::char_traits<char> >
> and live in the std namespace. All this is clearly described by the
> Dwarf tree structure.
> Of course in this case, we're speaking about incomplete types here, and
> we don't know they're really not simple structures. Thus applying this
> unification logic would is a bit dangerous.
Exactly.
It is impossible to get this reliably right for incomplete types.
However, I think we should do the best we can. I haven't thought
much about the implementation details yet though.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 16:57 ` Daniel Jacobowitz
2006-08-31 17:41 ` Frédéric Riss
@ 2006-08-31 19:48 ` Michael Veksler
2006-08-31 19:52 ` Daniel Jacobowitz
1 sibling, 1 reply; 23+ messages in thread
From: Michael Veksler @ 2006-08-31 19:48 UTC (permalink / raw)
To: Frederic RISS, gdb
Daniel Jacobowitz wrote:
> On Thu, Aug 31, 2006 at 06:48:04PM +0200, Frederic RISS wrote:
>
>> What happens is that you get 2 definitions of std::cout in the debug
>> information of your example. One definition for each file. The gotcha is
>> that neither of these definitions are complete. They're just empty
>>
...
> This is a deliberate choice on GCC's part, to reduce overly excessive
> debug information. There've been arguments about it in the past. My
>
From bits/ostream.tcc header file:
// Inhibit implicit instantiations for required instantiations,
// which are defined via explicit instantiations elsewhere.
// NB: This syntax is a GNU extension.
#if _GLIBCXX_EXTERN_TEMPLATE
extern template class basic_ostream<char>;
> feeling is that we will end up with something like a -gfull argument
> to force the extra information to be emitted. GDB needs to work as
> well as possible anyway.
>
>
Reading it more, one can force full instantiation of ostream:
g++ -g -D_GLIBCXX_EXTERN_TEMPLATE=0 myCout.cpp cout-gdb.cpp
Now everything works, and it is not that much bigger.
>> The first 'p x.Print(std::cout)' works because at this point, the
>> debugger has only read the full debug information of the first file.
>> This file contains a definition of std::cout and the definition of
>> B::Print which both point to the same instance of the std::ostream type.
>> Being the same instance, even if the type is incomplete GDB resolves the
>> overload correctly.
>> After you've referenced 'myCout' which is defined in the second file,
>> the debug info of the latter has been read, bringing a second definition
>> of std::cout in the global scope. This second definition is found by
>> further lookups of this symbol, and this time, the symbol type isn't the
>> same instance as before. GDB tries to compare to incomplete types and of
>> course it fails...
>>
>
> This is a problem with GDB, that I've always been amazed we didn't
> hit more often. It's a very difficult problem and I don't really know
> what we should be doing about it. I don't know if there's a standard
> term for this, but I've called it type unification in the past.
>
> We need some way to figure out that these are the same type, to the
> best of our knowledge.
>
>
It sounds similar to the problem of GDB on AIX (with XCOFF). There is a
PR on this:
http://sources.redhat.com/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gdb&pr=1170&return_url=http%3A%2F%2Fsources.redhat.com%2Fcgi-bin%2Fgnatsweb.pl%3Fdatabase%3Dgdb%26cmd%3Dsubmit%2520query%26category%3Dall%26severity%3Dall%26priority%3Dall%26responsible%3Dall%26submitter_id%3Dall%26state%3Dall%26ignoreclosed%3DIgnore%2520Closed%26class%3Dall%26synopsis%3D%26multitext%3DAIX%26columns%3Dcategory%26columns%3Dstate%26columns%3Dclass%26columns%3Dresponsible%26columns%3Dsynopsis%26displaydate%3DDisplay%2520Current%2520Date%26sortby%3DResponsible%26.cgifields%3Ddisplaydate%26.cgifields%3Dignoreclosed%26.cgifields%3Doriginatedbyme%26.cgifields%3Dcolumns
It happens when debug information is ordered in a different way than GDB
expects. This is something that native /bin/as does, and is not a fault
of gcc. According to X-COFF spec, the assembler is allowed to do this
reordering. I guess that this issue happens in different places GDB, but
it still has similar sound - GDB is sensitive to the order it reads
debug information.
--
Michael
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?)
2006-08-31 19:48 ` Michael Veksler
@ 2006-08-31 19:52 ` Daniel Jacobowitz
0 siblings, 0 replies; 23+ messages in thread
From: Daniel Jacobowitz @ 2006-08-31 19:52 UTC (permalink / raw)
To: Michael Veksler; +Cc: Frederic RISS, gdb
On Thu, Aug 31, 2006 at 10:48:43PM +0300, Michael Veksler wrote:
> >This is a deliberate choice on GCC's part, to reduce overly excessive
> >debug information. There've been arguments about it in the past. My
> >
> From bits/ostream.tcc header file:
> // Inhibit implicit instantiations for required instantiations,
> // which are defined via explicit instantiations elsewhere.
> // NB: This syntax is a GNU extension.
> #if _GLIBCXX_EXTERN_TEMPLATE
> extern template class basic_ostream<char>;
No, that's irrelevant to what I was talking about; some parts of the
debug info are done only with the class's key method. But...
> >feeling is that we will end up with something like a -gfull argument
> >to force the extra information to be emitted. GDB needs to work as
> >well as possible anyway.
> >
> >
> Reading it more, one can force full instantiation of ostream:
> g++ -g -D_GLIBCXX_EXTERN_TEMPLATE=0 myCout.cpp cout-gdb.cpp
> Now everything works, and it is not that much bigger.
...this causes the key method to be in the header for every compilation
unit, IIUC.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2006-08-31 19:52 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-08-30 10:11 How to call operator<< functions? Michael Veksler
2006-08-30 11:13 ` Frederic RISS
2006-08-30 13:30 ` Frederic RISS
2006-08-30 13:40 ` Breakpoint Handling in GDB Veenu Verma (AS/EAB)
2006-08-30 13:43 ` Daniel Jacobowitz
2006-08-30 20:30 ` Michael Snyder
2006-08-31 11:34 ` Get versioned minsyms from dynamic symtab (Was: Re: How to call operator<< functions?) Frederic RISS
2006-08-31 12:09 ` Michael Veksler
2006-08-31 12:26 ` Frederic RISS
2006-08-31 13:02 ` Michael Veksler
2006-08-31 13:23 ` Frederic RISS
2006-08-31 16:48 ` Frederic RISS
2006-08-31 16:57 ` Daniel Jacobowitz
2006-08-31 17:41 ` Frédéric Riss
2006-08-31 17:45 ` Daniel Jacobowitz
2006-08-31 19:48 ` Michael Veksler
2006-08-31 19:52 ` Daniel Jacobowitz
2006-08-30 12:46 ` How to call operator<< functions? Daniel Jacobowitz
2006-08-30 20:05 ` Michael Veksler
2006-08-30 20:24 ` Daniel Jacobowitz
2006-08-30 20:45 ` Michael Veksler
2006-08-30 20:54 ` Daniel Jacobowitz
2006-08-31 12:05 ` Michael Veksler
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox