Thread overview
Debugging D code with GDB
Nov 27, 2021
Eduard Staniloiu
Nov 27, 2021
Alexey
Nov 28, 2021
user1234
Nov 28, 2021
russhy
Nov 28, 2021
user1234
Nov 28, 2021
Iain Buclaw
Nov 29, 2021
Luís Ferreira
Nov 30, 2021
Iain Buclaw
Dec 02, 2021
Eduard Staniloiu
Jan 05, 2022
Luís Ferreira
November 27, 2021

Hello,

I'm trying to use gdb to debug D binaries, but I'm having trouble accessing the methods of a struct or class. It seems that gdb doesn't see them.

Given the following simple example

// test.d
struct S
{
    int x;

    void myPrint() { writefln("x is %s\n", x); }
}

void main(string[] args)
{
    S s;
}

Compile the source file with debug simbols (dmd -g test.d -of=test) and open the binary with gdb (gdb test) and run the following

> break _Dmain # break at D entry point
> run
> ptype s
type = struct test.S {
    int x;
}
> print s.myPrint()
Structure has no component named myPrint.

As you can see, when I try to access the myPrint() method I get the error
"Structure has no component named myPrint."

Looking up gdb's bugzilla, I've found this issue [0] that basically says that gdb treats D as C code (and that would explain why it doesn't look for function definitions inside D structs).

A simple "fix"/"hack" to this problem is to define a helper function that will take my symbol as a parameter and internally call the function that I need, like below:

extern (C) void helper(ref S s) { s.myPrint(); }

While this does the job for this trivial example, it doesn't scale for a real project.

Are there any solutions to this problem?

Looking forward to your answers,
Edi

[0] - https://sourceware.org/bugzilla/show_bug.cgi?id=22480

November 27, 2021

I found what Nemiver is much better for debugging D programs. With GDB I've got many problems, don't remember exactly. Thou I've used it through ddd, so maybe it's ddd problems, not exactly GDB's

November 28, 2021

On Saturday, 27 November 2021 at 14:17:11 UTC, Eduard Staniloiu wrote:

>

Hello,

I'm trying to use gdb to debug D binaries, but I'm having trouble accessing the methods of a struct or class. It seems that gdb doesn't see them.

[...]

Looking forward to your answers,
Edi

[0] - https://sourceware.org/bugzilla/show_bug.cgi?id=22480

Hello, while I never evaluate calls during debugging I've managed to find
a way : you can call the mangled name so for

#!dmd -g
module a;

import std.stdio;

struct S
{
    int myPrint(){return 8;}
}

pragma(msg, S.myPrint.mangleof);
int main(string[] args)
{
    S s;
    return 0;
}

in gdb CLI

p (int) _D1a1S7myPrintMFZi(s)
$1 = 8

works. Note that for some reasons writefln causes a crash, that's why I've modified the example.

The problem is that my workaround does not scale better than your.

November 28, 2021

On Sunday, 28 November 2021 at 14:53:17 UTC, user1234 wrote:

>

...

there is a plugin to demangle things automatically

https://github.com/ANtlord/gdb-ddemangle

November 28, 2021

On Sunday, 28 November 2021 at 16:44:38 UTC, russhy wrote:

>

On Sunday, 28 November 2021 at 14:53:17 UTC, user1234 wrote:

>

...

there is a plugin to demangle things automatically

https://github.com/ANtlord/gdb-ddemangle

That's off-topic. The point here is that you can (unfortunately) only evaluate the call using the mangled form, it's not about transforming the output.

Actually what would be useful is a plugin the mangle the call in custom expression before passing it to gdb ;)

November 28, 2021

On Saturday, 27 November 2021 at 14:17:11 UTC, Eduard Staniloiu wrote:

>

Hello,

I'm trying to use gdb to debug D binaries, but I'm having trouble accessing the methods of a struct or class. It seems that gdb doesn't see them.

Given the following simple example

// test.d
struct S
{
    int x;

    void myPrint() { writefln("x is %s\n", x); }
}

void main(string[] args)
{
    S s;
}

Compile the source file with debug simbols (dmd -g test.d -of=test) and open the binary with gdb (gdb test) and run the following

> break _Dmain # break at D entry point
> run
> ptype s
type = struct test.S {
    int x;
}
> print s.myPrint()
Structure has no component named myPrint.

As you can see, when I try to access the myPrint() method I get the error
"Structure has no component named myPrint."

DMD doesn't emit this information. GDB can't work miracles when the compiler isn't pulling its own weight.

November 29, 2021
On Sun, 2021-11-28 at 21:59 +0000, Iain Buclaw via Digitalmars-d-learn wrote:
> On Saturday, 27 November 2021 at 14:17:11 UTC, Eduard Staniloiu wrote:
> > Hello,
> > 
> > I'm trying to use `gdb` to debug D binaries, but I'm having trouble accessing the methods of a struct or class. It seems that `gdb` doesn't see them.
> > 
> > Given the following simple example
> > ```
> > // test.d
> > struct S
> > {
> >     int x;
> > 
> >     void myPrint() { writefln("x is %s\n", x); }
> > }
> > 
> > void main(string[] args)
> > {
> >     S s;
> > }
> > ```
> > Compile the source file with debug simbols (`dmd -g test.d
> > -of=test`) and open the binary with gdb (`gdb test`) and run
> > the following
> > 
> > ```
> > > break _Dmain # break at D entry point
> > > run
> > > ptype s
> > type = struct test.S {
> >     int x;
> > }
> > > print s.myPrint()
> > Structure has no component named myPrint.
> > ```
> > 
> > As you can see, when I try to access the `myPrint()` method I
> > get the error
> > "Structure has no component named myPrint."
> > 
> 
> DMD doesn't emit this information. GDB can't work miracles when the compiler isn't pulling its own weight.

I confirm this is an issue with DMD. I filed a bug in the issue tracker, in case you want to follow: https://issues.dlang.org/show_bug.cgi?id=22551

Anyway, DMD exports the symbol, it should work if you do something like `myPrint(&s)`, but I think there is another problem on calling it, due to defective calling convention on both DMD and LDC implementations.

LDC exports the symbol correctly, although.

-- 
Sincerely,
Luís Ferreira @ lsferreira.net



November 30, 2021
On Monday, 29 November 2021 at 14:48:21 UTC, Luís Ferreira wrote:
> On Sun, 2021-11-28 at 21:59 +0000, Iain Buclaw via Digitalmars-d-learn wrote:
>> 
>> DMD doesn't emit this information. GDB can't work miracles when the compiler isn't pulling its own weight.
>
> I confirm this is an issue with DMD. I filed a bug in the issue tracker, in case you want to follow: https://issues.dlang.org/show_bug.cgi?id=22551
>
> Anyway, DMD exports the symbol, it should work if you do something like `myPrint(&s)`, but I think there is another problem on calling it, due to defective calling convention on both DMD and LDC implementations.
>
> LDC exports the symbol correctly, although.

Indeed, gdb assumes calling convention is same as default for target (actually its been years since I last looked, but are calling conventions tags in dwarf? Does gdb know about functions with thiscall or regparm attributes?)

Another thing on the gdb side, it is currently missing D language support for overloads, so that the correct function would be picked when you call e.g std.math.sin(1f).
December 02, 2021
On Tuesday, 30 November 2021 at 09:01:38 UTC, Iain Buclaw wrote:
> On Monday, 29 November 2021 at 14:48:21 UTC, Luís Ferreira wrote:
>> [...]
>
> Indeed, gdb assumes calling convention is same as default for target (actually its been years since I last looked, but are calling conventions tags in dwarf? Does gdb know about functions with thiscall or regparm attributes?)
>
> Another thing on the gdb side, it is currently missing D language support for overloads, so that the correct function would be picked when you call e.g std.math.sin(1f).

So currently the workaround is they way to go.

Thank you all for your help and suggestions!
January 05, 2022
On Tue, 2021-11-30 at 09:01 +0000, Iain Buclaw via Digitalmars-d-learn wrote:
> On Monday, 29 November 2021 at 14:48:21 UTC, Luís Ferreira wrote:
> > On Sun, 2021-11-28 at 21:59 +0000, Iain Buclaw via Digitalmars-d-learn wrote:
> > > 
> > > DMD doesn't emit this information. GDB can't work miracles when the compiler isn't pulling its own weight.
> > 
> > I confirm this is an issue with DMD. I filed a bug in the issue tracker, in case you want to follow: https://issues.dlang.org/show_bug.cgi?id=22551
> > 
> > Anyway, DMD exports the symbol, it should work if you do something like `myPrint(&s)`, but I think there is another problem on calling it, due to defective calling convention on both DMD and LDC implementations.
> > 
> > LDC exports the symbol correctly, although.
> 
> Indeed, gdb assumes calling convention is same as default for target (actually its been years since I last looked, but are calling conventions tags in dwarf? Does gdb know about functions with thiscall or regparm attributes?)
> 

Yes, it is specified in 7.15. Calling Convention Encodings in DWARF standard. You can use DW_AT_calling_convention attribute to specify a certain calling convention, being DW_CC_normal the default value. But you have very limited number of calling conventions available, being the rest considered vendor-specific. You might want DW_CC_BORLAND_thiscall ?

-- 
Sincerely,
Luís Ferreira @ lsferreira.net