Bug 30576 - "Too few arguments in function call." when trying to print function return values bigger than 16 bytes
Summary: "Too few arguments in function call." when trying to print function return va...
Status: RESOLVED NOTABUG
Alias: None
Product: gdb
Classification: Unclassified
Component: d (show other bugs)
Version: 13.1
: P2 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-06-22 08:40 UTC by Vladimir Panteleev
Modified: 2024-11-28 07:25 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Vladimir Panteleev 2023-06-22 08:40:50 UTC
If an extern(C) function in a D program has a return value larger than 16 bytes, trying to call it and print its return value from gdb results in the error message "Too few arguments in function call.".

Reproducer:

cat > bug.d <<EOF
extern(C) auto a() { return (ubyte[16]).init; }
extern(C) auto b() { return (ubyte[17]).init; }
void main(){}
EOF

dmd -g bug

gdb -ex start \
	-ex 'echo === a() ===\n' \
	-ex 'p a()' \
	-ex 'echo === b() ===\n' \
	-ex 'p b()' \
	-ex 'stop' \
	-ex 'quit' \
	./bug
Comment 1 liushuyu 2024-11-28 04:00:21 UTC
I think this has been fixed (I am using GDB 15):

gdb --batch -x bug.gdb ./bug1                                                                                                                                                           

Temporary breakpoint 1 at 0x251ea: file bug.d, line 3.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Temporary breakpoint 1, D main () at bug.d:3
3       void main(){}
=== a() ===
$1 = '\000' <repeats 15 times>
=== b() ===
$2 = '\000' <repeats 16 times>
A debugging session is active.

        Inferior 1 [process 681157] will be killed.

Quit anyway? (y or n) [answered Y; input not from terminal]
Comment 2 Vladimir Panteleev 2024-11-28 04:14:44 UTC
It still happens here. GDB 15.1, DMD v2.109.1.
Comment 3 liushuyu 2024-11-28 04:25:30 UTC
(In reply to Vladimir Panteleev from comment #2)
> It still happens here. GDB 15.1, DMD v2.109.1.

Oh, I see now, you were using the DMD compiler.

After some investigations, I think it's a DMD bug. Here's the DWARF dump of the function bug.b():

0x000000a9:   DW_TAG_subprogram
                DW_AT_sibling   (0x000000e7)
                DW_AT_MIPS_linkage_name ("b")
                DW_AT_type      (0x00000095 "ubyte[17]")
                DW_AT_external  (0x01)
                DW_AT_pure      (0x01)
                DW_AT_name      ("bug.b")
                DW_AT_decl_file ("/tmp/./bug.d")
                DW_AT_decl_line (2)
                DW_AT_decl_column       (16)
                DW_AT_low_pc    (0x0000000000042728)
                DW_AT_high_pc   (0x0000000000042754)
                DW_AT_frame_base        (0x0000004c:
                   [0x0000000000042728, 0x0000000000042729): DW_OP_breg7 RSP+8
                   [0x0000000000042729, 0x000000000004272b): DW_OP_breg7 RSP+16
                   [0x000000000004272b, 0x0000000000042754): DW_OP_breg6 RBP+16)

0x000000d3:     DW_TAG_formal_parameter
                  DW_AT_name    ("__HID1")
                  DW_AT_type    (0x000000a4 "ubyte (*)[17]")
                  DW_AT_artificial      (0x00)
                  DW_AT_decl_file       ("/tmp/./bug.d")
                  DW_AT_decl_line       (0)
                  DW_AT_decl_column     (0)
                  DW_AT_location        (DW_OP_fbreg -24)

It seems like DMD accidentally included the stack return argument in the debug data, which is incorrect (according to the DWARF v5 spec, DW_TAG_formal_parameter is only valid for parameters passing into the function, not return values).

If the DWARF dump looks abstract, basically, the debug information describes the function as:

extern(C) ubyte[17] b(ubyte[17] __HID1);

So GDB thought you should pass something to the function.

In contrast, the GDC compiler wrote the debug information like this:

0x00000184:   DW_TAG_subprogram
                DW_AT_external  (true)
                DW_AT_name      ("b")
                DW_AT_decl_file ("/tmp/bug.d")
                DW_AT_decl_line (2)
                DW_AT_decl_column       (16)
                DW_AT_type      (0x00000166 "ubyte[17]")
                DW_AT_low_pc    (0x00000000000251c9)
                DW_AT_high_pc   (0x00000000000251e6)
                DW_AT_frame_base        (DW_OP_call_frame_cfa)
                DW_AT_call_all_calls    (true)

Which is the correct definition for your bug.b function.
Comment 4 liushuyu 2024-11-28 04:27:18 UTC
(In reply to liushuyu from comment #3)
> (In reply to Vladimir Panteleev from comment #2)
> > It still happens here. GDB 15.1, DMD v2.109.1.
> 
> Oh, I see now, you were using the DMD compiler.
> 
> After some investigations, I think it's a DMD bug. Here's the DWARF dump of
> the function bug.b():
> 
> 0x000000a9:   DW_TAG_subprogram
>                 DW_AT_sibling   (0x000000e7)
>                 DW_AT_MIPS_linkage_name ("b")
>                 DW_AT_type      (0x00000095 "ubyte[17]")
>                 DW_AT_external  (0x01)
>                 DW_AT_pure      (0x01)
>                 DW_AT_name      ("bug.b")
>                 DW_AT_decl_file ("/tmp/./bug.d")
>                 DW_AT_decl_line (2)
>                 DW_AT_decl_column       (16)
>                 DW_AT_low_pc    (0x0000000000042728)
>                 DW_AT_high_pc   (0x0000000000042754)
>                 DW_AT_frame_base        (0x0000004c:
>                    [0x0000000000042728, 0x0000000000042729): DW_OP_breg7
> RSP+8
>                    [0x0000000000042729, 0x000000000004272b): DW_OP_breg7
> RSP+16
>                    [0x000000000004272b, 0x0000000000042754): DW_OP_breg6
> RBP+16)
> 
> 0x000000d3:     DW_TAG_formal_parameter
>                   DW_AT_name    ("__HID1")
>                   DW_AT_type    (0x000000a4 "ubyte (*)[17]")
>                   DW_AT_artificial      (0x00)
>                   DW_AT_decl_file       ("/tmp/./bug.d")
>                   DW_AT_decl_line       (0)
>                   DW_AT_decl_column     (0)
>                   DW_AT_location        (DW_OP_fbreg -24)
> 
> It seems like DMD accidentally included the stack return argument in the
> debug data, which is incorrect (according to the DWARF v5 spec,
> DW_TAG_formal_parameter is only valid for parameters passing into the
> function, not implicit return values defined by ABI).
> 
> If the DWARF dump looks abstract the debug information describes
> the function as:
> 
> extern(C) ubyte[17] b(ubyte[17] __HID1);
> 
> So GDB thought you should pass something to the function.
> 
> In contrast, the GDC compiler wrote the debug information like this:
> 
> 0x00000184:   DW_TAG_subprogram
>                 DW_AT_external  (true)
>                 DW_AT_name      ("b")
>                 DW_AT_decl_file ("/tmp/bug.d")
>                 DW_AT_decl_line (2)
>                 DW_AT_decl_column       (16)
>                 DW_AT_type      (0x00000166 "ubyte[17]")
>                 DW_AT_low_pc    (0x00000000000251c9)
>                 DW_AT_high_pc   (0x00000000000251e6)
>                 DW_AT_frame_base        (DW_OP_call_frame_cfa)
>                 DW_AT_call_all_calls    (true)
> 
> Which is the correct definition for your bug.b function.
Comment 5 Vladimir Panteleev 2024-11-28 07:23:28 UTC
Thank you, DMD bug filed: https://issues.dlang.org/show_bug.cgi?id=24888