Jump to page: 1 2
Thread overview
Stack tracing on Linux ?
Apr 02, 2009
Georg Wrede
Apr 02, 2009
Simon Gomizelj
Apr 02, 2009
Georg Wrede
Apr 03, 2009
Fawzi Mohamed
Apr 03, 2009
Walter Bright
Apr 03, 2009
Fawzi Mohamed
Apr 03, 2009
Walter Bright
Apr 02, 2009
Fawzi Mohamed
Apr 02, 2009
Georg Wrede
Apr 02, 2009
Sean Kelly
Apr 03, 2009
Fawzi Mohamed
Apr 04, 2009
Jérôme M. Berger
Apr 03, 2009
Christopher Wright
Apr 03, 2009
Fawzi Mohamed
Apr 10, 2009
Georg Wrede
April 02, 2009
With gdb I can either debug a core dump or an actual running process. For example, with

import std.stdio;

int main()
{
    readWrite();
    return 8;
}

void readWrite()
{
    auto line = readln();   // here it waits, and that's when I debug
                            // in another window
    write("Rivi oli: ", line);
}

I get the following stack trace (it looks the same whether I debug a core dump or a running instance)

#0  0x00251416 in __kernel_vsyscall ()
#1  0x00591a93 in __read_nocancel () from /lib/libc.so.6
#2  0x00528cee in _IO_new_file_underflow (fp=0x62e420) at fileops.c:598
#3  0x0052c17a in __underflow (fp=0x62e420) at genops.c:361
#4  0x0051e648 in _IO_getdelim (lineptr=0xbf94ec8c, n=0xbf94ec90,
    delimiter=10, fp=0x62e420) at iogetdelim.c:79
#5  0x080505bb in _D3std5stdio6readlnFPS3std1c5stdio6_iobufKAawZk ()
#6  0x080504d0 in _D3std5stdio6readlnFPS3std1c5stdio6_iobufwZAya ()
#7  0x0804931a in _D5read29readWriteFZv ()
#8  0x00000000 in ?? ()

This is not perfect, 5..7 are functions written in D, but main is missing. Then, trying to examine a core dump from something that gets a segfault, I wrote the following, expecting that I'd get a grandiose stack trace


$ cat npe.d
import std.stdio;

int main()
{
    return foo(3);
}

int foo(int a)
{
    return 1 + bar(a - 3);
}

int bar(int b)
{
    return 1 + car(b - 3);
}

int car(int c)
{
    return 1 + dar(c - 3);
}

int dar(int d)
{
    return 1 + * cast(int*) d; // null pointer exception
}



Turns out I got zilch!

#0  0x08049118 in _D3npe3darFiZi ()
#1  0xfffffffa in ?? ()

I have DMD on Fedora 10, and used
dmd -g -debug -v read2.d
to compile. Incidentally, using
dmd -gc -debug -v read2.d
does seem to give the same stack trace.

April 02, 2009
On Thu, 02 Apr 2009 04:56:46 -0400, Georg Wrede <georg.wrede@iki.fi> wrote:

> With gdb I can either debug a core dump or an actual running process. For example, with
>
> import std.stdio;
>
> int main()
> {
>      readWrite();
>      return 8;
> }
>
> void readWrite()
> {
>      auto line = readln();   // here it waits, and that's when I debug
>                              // in another window
>      write("Rivi oli: ", line);
> }
>
> I get the following stack trace (it looks the same whether I debug a core dump or a running instance)
>
> #0  0x00251416 in __kernel_vsyscall ()
> #1  0x00591a93 in __read_nocancel () from /lib/libc.so.6
> #2  0x00528cee in _IO_new_file_underflow (fp=0x62e420) at fileops.c:598
> #3  0x0052c17a in __underflow (fp=0x62e420) at genops.c:361
> #4  0x0051e648 in _IO_getdelim (lineptr=0xbf94ec8c, n=0xbf94ec90,
>      delimiter=10, fp=0x62e420) at iogetdelim.c:79
> #5  0x080505bb in _D3std5stdio6readlnFPS3std1c5stdio6_iobufKAawZk ()
> #6  0x080504d0 in _D3std5stdio6readlnFPS3std1c5stdio6_iobufwZAya ()
> #7  0x0804931a in _D5read29readWriteFZv ()
> #8  0x00000000 in ?? ()
>
> This is not perfect, 5..7 are functions written in D, but main is missing. Then, trying to examine a core dump from something that gets a segfault, I wrote the following, expecting that I'd get a grandiose stack trace
>
>
> $ cat npe.d
> import std.stdio;
>
> int main()
> {
>      return foo(3);
> }
>
> int foo(int a)
> {
>      return 1 + bar(a - 3);
> }
>
> int bar(int b)
> {
>      return 1 + car(b - 3);
> }
>
> int car(int c)
> {
>      return 1 + dar(c - 3);
> }
>
> int dar(int d)
> {
>      return 1 + * cast(int*) d; // null pointer exception
> }
>
>
>
> Turns out I got zilch!
>
> #0  0x08049118 in _D3npe3darFiZi ()
> #1  0xfffffffa in ?? ()
>
> I have DMD on Fedora 10, and used
> dmd -g -debug -v read2.d
> to compile. Incidentally, using
> dmd -gc -debug -v read2.d
> does seem to give the same stack trace.
>

While I can't explain why gdb and dmd don't seem to work nicely together, you'd have much better luck using ldc.
Compiling with ldc, this is the backtrace I got when debugging read2.d on my maching (and is what you're probably looking for):

(gdb) run
Starting program: /data/Code/D/error
[Thread debugging using libthread_db enabled]
[New Thread 0xb7d656c0 (LWP 14104)]

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb7d656c0 (LWP 14104)]
0x080495fe in _D5error3darFiZi (d=-6) at error.d:23
23	    return 1 + * cast(int*) d; // null pointer exception
(gdb) backtrace
#0  0x080495fe in _D5error3darFiZi (d=-6) at error.d:23
#1  0x080495e3 in _D5error3carFiZi (c=-3) at error.d:18
#2  0x080495c3 in _D5error3barFiZi (b=0) at error.d:13
#3  0x080495a3 in _D5error3fooFiZi (a=3) at error.d:8
#4  0x0804957d in _Dmain () at error.d:3
#5  0x0804dd0a in _D6dmain24mainUiPPaPPaZi7runMainMFZv ()
#6  0x0804d9c7 in _D6dmain24mainUiPPaPPaZi7tryExecMFDFZvZv ()
#7  0x0804dd4d in _D6dmain24mainUiPPaPPaZi6runAllMFZv ()
#8  0x0804d9c7 in _D6dmain24mainUiPPaPPaZi7tryExecMFDFZvZv ()
#9  0x0804d946 in main ()

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
April 02, 2009
Well inlined functions will have no frame, also last call optimization (tail optimization) removes the frame.
the backtrace typically gets the return address (i.e. the adress of the next instruction, not of the calling instruction).
Normally the code tries to guess the calling instruction as the one before the return instruction, but it does not always work.
So one has to expect that the backtrace might miss some frames.
But normally this is not a problem.
The tracing of tango svn version (that uses libc backtrace) seems to work rather well.
It does not give you the names, but as said that is due to a license problem.

gdb uses the same tools (and libbdf), that as jive has shown works well (but is GPL).
So I think that things are working as expected, even if maybe not as you would like :)

Fawzi

On 2009-04-02 10:56:46 +0200, Georg Wrede <georg.wrede@iki.fi> said:

> With gdb I can either debug a core dump or an actual running process. For example, with
> 
> import std.stdio;
> 
> int main()
> {
>      readWrite();
>      return 8;
> }
> 
> void readWrite()
> {
>      auto line = readln();   // here it waits, and that's when I debug
>                              // in another window
>      write("Rivi oli: ", line);
> }
> 
> I get the following stack trace (it looks the same whether I debug a core dump or a running instance)
> 
> #0  0x00251416 in __kernel_vsyscall ()
> #1  0x00591a93 in __read_nocancel () from /lib/libc.so.6
> #2  0x00528cee in _IO_new_file_underflow (fp=0x62e420) at fileops.c:598
> #3  0x0052c17a in __underflow (fp=0x62e420) at genops.c:361
> #4  0x0051e648 in _IO_getdelim (lineptr=0xbf94ec8c, n=0xbf94ec90,
>      delimiter=10, fp=0x62e420) at iogetdelim.c:79
> #5  0x080505bb in _D3std5stdio6readlnFPS3std1c5stdio6_iobufKAawZk ()
> #6  0x080504d0 in _D3std5stdio6readlnFPS3std1c5stdio6_iobufwZAya ()
> #7  0x0804931a in _D5read29readWriteFZv ()
> #8  0x00000000 in ?? ()
> 
> This is not perfect, 5..7 are functions written in D, but main is missing. Then, trying to examine a core dump from something that gets a segfault, I wrote the following, expecting that I'd get a grandiose stack trace
> 
> 
> $ cat npe.d
> import std.stdio;
> 
> int main()
> {
>      return foo(3);
> }
> 
> int foo(int a)
> {
>      return 1 + bar(a - 3);
> }
> 
> int bar(int b)
> {
>      return 1 + car(b - 3);
> }
> 
> int car(int c)
> {
>      return 1 + dar(c - 3);
> }
> 
> int dar(int d)
> {
>      return 1 + * cast(int*) d; // null pointer exception
> }
> 
> 
> 
> Turns out I got zilch!
> 
> #0  0x08049118 in _D3npe3darFiZi ()
> #1  0xfffffffa in ?? ()
> 
> I have DMD on Fedora 10, and used
> dmd -g -debug -v read2.d
> to compile. Incidentally, using
> dmd -gc -debug -v read2.d
> does seem to give the same stack trace.


April 02, 2009
Fawzi Mohamed wrote:
> Well inlined functions will have no frame, also last call optimization (tail optimization) removes the frame.

If I were to write a compiler, then using "-g -debug", etc. would make sure neither happens!

> the backtrace typically gets the return address (i.e. the adress of the next instruction, not of the calling instruction).
> Normally the code tries to guess the calling instruction as the one before the return instruction, but it does not always work.

A first idea is to have the compiler insert a few NOPs when compiling with -debug, but then again if it were that easy, somebody else would've thought of it already.

> So one has to expect that the backtrace might miss some frames.
> But normally this is not a problem.

While I've seldom needed debuggin tools or stack tracing, I can imagine they're indispensable for people who have to quickly fix others' code. I guess most folks here, especially Walter(?) really do most of their coding on "new" and "own" things, where there's less need for such? But in a busy corporate environment with dozens of coders on the project, and people having to debug (or actually ending up because the called function doesn't work right) each other's code, it's different.

> The tracing of tango svn version (that uses libc backtrace) seems to work rather well.
> It does not give you the names, but as said that is due to a license problem.

Aarrghhh. What most frustrates me is when something obvious can't be done because of external trivialities.

> gdb uses the same tools (and libbdf), that as jive has shown works well (but is GPL).
> So I think that things are working as expected, even if maybe not as you would like :)

It's a shame.

April 02, 2009
Simon Gomizelj wrote:
> On Thu, 02 Apr 2009 04:56:46 -0400, Georg Wrede <georg.wrede@iki.fi> wrote:
> 
>> With gdb I can either debug a core dump or an actual running process. For example, with
>>
>> import std.stdio;
>>
>> int main()
>> {
>>      readWrite();
>>      return 8;
>> }
>>
>> void readWrite()
>> {
>>      auto line = readln();   // here it waits, and that's when I debug
>>                              // in another window
>>      write("Rivi oli: ", line);
>> }
>>
>> I get the following stack trace (it looks the same whether I debug a core dump or a running instance)
>>
>> #0  0x00251416 in __kernel_vsyscall ()
>> #1  0x00591a93 in __read_nocancel () from /lib/libc.so.6
>> #2  0x00528cee in _IO_new_file_underflow (fp=0x62e420) at fileops.c:598
>> #3  0x0052c17a in __underflow (fp=0x62e420) at genops.c:361
>> #4  0x0051e648 in _IO_getdelim (lineptr=0xbf94ec8c, n=0xbf94ec90,
>>      delimiter=10, fp=0x62e420) at iogetdelim.c:79
>> #5  0x080505bb in _D3std5stdio6readlnFPS3std1c5stdio6_iobufKAawZk ()
>> #6  0x080504d0 in _D3std5stdio6readlnFPS3std1c5stdio6_iobufwZAya ()
>> #7  0x0804931a in _D5read29readWriteFZv ()
>> #8  0x00000000 in ?? ()
>>
>> This is not perfect, 5..7 are functions written in D, but main is missing. Then, trying to examine a core dump from something that gets a segfault, I wrote the following, expecting that I'd get a grandiose stack trace
>>
>>
>> $ cat npe.d
>> import std.stdio;
>>
>> int main()
>> {
>>      return foo(3);
>> }
>>
>> int foo(int a)
>> {
>>      return 1 + bar(a - 3);
>> }
>>
>> int bar(int b)
>> {
>>      return 1 + car(b - 3);
>> }
>>
>> int car(int c)
>> {
>>      return 1 + dar(c - 3);
>> }
>>
>> int dar(int d)
>> {
>>      return 1 + * cast(int*) d; // null pointer exception
>> }
>>
>>
>>
>> Turns out I got zilch!
>>
>> #0  0x08049118 in _D3npe3darFiZi ()
>> #1  0xfffffffa in ?? ()
>>
>> I have DMD on Fedora 10, and used
>> dmd -g -debug -v read2.d
>> to compile. Incidentally, using
>> dmd -gc -debug -v read2.d
>> does seem to give the same stack trace.
>>
> 
> While I can't explain why gdb and dmd don't seem to work nicely together, you'd have much better luck using ldc.
> Compiling with ldc, this is the backtrace I got when debugging read2.d on my maching (and is what you're probably looking for):
> 
> (gdb) run
> Starting program: /data/Code/D/error
> [Thread debugging using libthread_db enabled]
> [New Thread 0xb7d656c0 (LWP 14104)]
> 
> Program received signal SIGSEGV, Segmentation fault.
> [Switching to Thread 0xb7d656c0 (LWP 14104)]
> 0x080495fe in _D5error3darFiZi (d=-6) at error.d:23
> 23        return 1 + * cast(int*) d; // null pointer exception
> (gdb) backtrace
> #0  0x080495fe in _D5error3darFiZi (d=-6) at error.d:23
> #1  0x080495e3 in _D5error3carFiZi (c=-3) at error.d:18
> #2  0x080495c3 in _D5error3barFiZi (b=0) at error.d:13
> #3  0x080495a3 in _D5error3fooFiZi (a=3) at error.d:8
> #4  0x0804957d in _Dmain () at error.d:3
> #5  0x0804dd0a in _D6dmain24mainUiPPaPPaZi7runMainMFZv ()
> #6  0x0804d9c7 in _D6dmain24mainUiPPaPPaZi7tryExecMFDFZvZv ()
> #7  0x0804dd4d in _D6dmain24mainUiPPaPPaZi6runAllMFZv ()
> #8  0x0804d9c7 in _D6dmain24mainUiPPaPPaZi7tryExecMFDFZvZv ()
> #9  0x0804d946 in main ()

Ah, this looks nice. And the file name shows in the function names.

If everyone wasn't telling me it's a licence issue, I'd take it for granted there's a bug in DMD.
April 02, 2009
== Quote from Georg Wrede (georg.wrede@iki.fi)'s article
> Fawzi Mohamed wrote:
> >
> > The tracing of tango svn version (that uses libc backtrace) seems to
> > work rather well.
> > It does not give you the names, but as said that is due to a license
> > problem.
> Aarrghhh. What most frustrates me is when something obvious can't be done because of external trivialities.

The Tango plugin architecture for backtrace was designed so that the backtrace code doesn't have to be integrated into Tango itself, eliminating the license problem.  But I can see how this might be a problem if you want to bundle a backtrace library with Tango :-)
April 03, 2009
On 2009-04-02 20:51:26 +0200, Georg Wrede <georg.wrede@iki.fi> said:

> Simon Gomizelj wrote:
>> On Thu, 02 Apr 2009 04:56:46 -0400, Georg Wrede <georg.wrede@iki.fi> wrote:
>> 
>>> With gdb I can either debug a core dump or an actual running process. For example, with
>>> 
>>> import std.stdio;
>>> 
>>> int main()
>>> {
>>>      readWrite();
>>>      return 8;
>>> }
>>> 
>>> void readWrite()
>>> {
>>>      auto line = readln();   // here it waits, and that's when I debug
>>>                              // in another window
>>>      write("Rivi oli: ", line);
>>> }
>>> 
>>> I get the following stack trace (it looks the same whether I debug a core dump or a running instance)
>>> 
>>> #0  0x00251416 in __kernel_vsyscall ()
>>> #1  0x00591a93 in __read_nocancel () from /lib/libc.so.6
>>> #2  0x00528cee in _IO_new_file_underflow (fp=0x62e420) at fileops.c:598
>>> #3  0x0052c17a in __underflow (fp=0x62e420) at genops.c:361
>>> #4  0x0051e648 in _IO_getdelim (lineptr=0xbf94ec8c, n=0xbf94ec90,
>>>      delimiter=10, fp=0x62e420) at iogetdelim.c:79
>>> #5  0x080505bb in _D3std5stdio6readlnFPS3std1c5stdio6_iobufKAawZk ()
>>> #6  0x080504d0 in _D3std5stdio6readlnFPS3std1c5stdio6_iobufwZAya ()
>>> #7  0x0804931a in _D5read29readWriteFZv ()
>>> #8  0x00000000 in ?? ()
>>> 
>>> This is not perfect, 5..7 are functions written in D, but main is missing. Then, trying to examine a core dump from something that gets a segfault, I wrote the following, expecting that I'd get a grandiose stack trace
>>> 
>>> 
>>> $ cat npe.d
>>> import std.stdio;
>>> 
>>> int main()
>>> {
>>>      return foo(3);
>>> }
>>> 
>>> int foo(int a)
>>> {
>>>      return 1 + bar(a - 3);
>>> }
>>> 
>>> int bar(int b)
>>> {
>>>      return 1 + car(b - 3);
>>> }
>>> 
>>> int car(int c)
>>> {
>>>      return 1 + dar(c - 3);
>>> }
>>> 
>>> int dar(int d)
>>> {
>>>      return 1 + * cast(int*) d; // null pointer exception
>>> }
>>> 
>>> 
>>> 
>>> Turns out I got zilch!
>>> 
>>> #0  0x08049118 in _D3npe3darFiZi ()
>>> #1  0xfffffffa in ?? ()
>>> 
>>> I have DMD on Fedora 10, and used
>>> dmd -g -debug -v read2.d
>>> to compile. Incidentally, using
>>> dmd -gc -debug -v read2.d
>>> does seem to give the same stack trace.
>>> 
>> 
>> While I can't explain why gdb and dmd don't seem to work nicely together, you'd have much better luck using ldc.
>> Compiling with ldc, this is the backtrace I got when debugging read2.d on my maching (and is what you're probably looking for):
>> 
>> (gdb) run
>> Starting program: /data/Code/D/error
>> [Thread debugging using libthread_db enabled]
>> [New Thread 0xb7d656c0 (LWP 14104)]
>> 
>> Program received signal SIGSEGV, Segmentation fault.
>> [Switching to Thread 0xb7d656c0 (LWP 14104)]
>> 0x080495fe in _D5error3darFiZi (d=-6) at error.d:23
>> 23        return 1 + * cast(int*) d; // null pointer exception
>> (gdb) backtrace
>> #0  0x080495fe in _D5error3darFiZi (d=-6) at error.d:23
>> #1  0x080495e3 in _D5error3carFiZi (c=-3) at error.d:18
>> #2  0x080495c3 in _D5error3barFiZi (b=0) at error.d:13
>> #3  0x080495a3 in _D5error3fooFiZi (a=3) at error.d:8
>> #4  0x0804957d in _Dmain () at error.d:3
>> #5  0x0804dd0a in _D6dmain24mainUiPPaPPaZi7runMainMFZv ()
>> #6  0x0804d9c7 in _D6dmain24mainUiPPaPPaZi7tryExecMFDFZvZv ()
>> #7  0x0804dd4d in _D6dmain24mainUiPPaPPaZi6runAllMFZv ()
>> #8  0x0804d9c7 in _D6dmain24mainUiPPaPPaZi7tryExecMFDFZvZv ()
>> #9  0x0804d946 in main ()
> 
> Ah, this looks nice. And the file name shows in the function names.
> 
> If everyone wasn't telling me it's a licence issue,
No the license issue is just for including this in tango

> I'd take it for granted there's a bug in DMD.

you are right, on mac with dmd I get the full trace, on linux not. About the missing line and file information I think dmd does not add that on mac/linux.

April 03, 2009
On 2009-04-02 21:18:55 +0200, Sean Kelly <sean@invisibleduck.org> said:

> == Quote from Georg Wrede (georg.wrede@iki.fi)'s article
>> Fawzi Mohamed wrote:
>>> 
>>> The tracing of tango svn version (that uses libc backtrace) seems to
>>> work rather well.
>>> It does not give you the names, but as said that is due to a license
>>> problem.
>> Aarrghhh. What most frustrates me is when something obvious can't be
>> done because of external trivialities.
> 
> The Tango plugin architecture for backtrace was designed so that the
> backtrace code doesn't have to be integrated into Tango itself, eliminating
> the license problem.  But I can see how this might be a problem if you
> want to bundle a backtrace library with Tango :-)

having some stacktracing by default there was the number one request at the tango reference, and also in the wish list for a while.
The idea is not to disallow external solutions, but to have something working there by default.
Please note that something using GPL code even as plugin forces the whole application to be GPL, which is not acceptable for anyone not wanting to release its application as GPL.

Fawzi

April 03, 2009
Fawzi Mohamed wrote:
> you are right, on mac with dmd I get the full trace, on linux not. About the missing line and file information I think dmd does not add that on mac/linux.

You can see using dumpobj -p on the object files that dmd *does* put in the information.
April 03, 2009
Georg Wrede wrote:
> Fawzi Mohamed wrote:
>> Well inlined functions will have no frame, also last call optimization (tail optimization) removes the frame.
> 
> If I were to write a compiler, then using "-g -debug", etc. would make sure neither happens!

However, closures in D1 have a stack frame that is within the creating function's stack frame, and gdb assumes that means a corrupt stack. There's no real way around this.
« First   ‹ Prev
1 2