llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28k stars 11.56k forks source link

[DWARF5][clang] Stack-passed call_site_parameters are not generated #94986

Open spevnev opened 3 months ago

spevnev commented 3 months ago

When compiling a C (I haven't tested other languages) function with more than 6 parameters on x86_64 (I haven't tested other architectures), its call_site will have at most 6 parameters, while the rest, which is stored on the stack (their DW_AT_location is DW_OP_fbreg), can only be seen as formal_parameters in the subprogram DIE.

I believe that this is a bug, since I can't find anything about this limitation in DWARF5 format.

Minimum example:

__attribute__((noinline)) void test(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) {
    printf("%d %d %d %d %d %d %d %d\n", a1, a2, a3, a4, a5, a6, a7, a8);
}

int main(void) {
    test(1,2,3,4,5,6,7,8);
    return 0;
}
$ clang -O2 -g3 example.c
$ llvm-dwarfdump ./a.out

DWARF dump of subprogram:

0x00000027:   DW_TAG_subprogram
                DW_AT_low_pc    (0x0000000000001140)
                DW_AT_high_pc   (0x0000000000001176)
                DW_AT_frame_base        (DW_OP_reg7 RSP)
                DW_AT_call_all_calls    (true)
                DW_AT_name      ("test")
                DW_AT_decl_file ("/app/examples/min.c")
                DW_AT_decl_line (3)
                DW_AT_prototyped        (true)
                DW_AT_external  (true)

0x00000032:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x0) loclist = 0x0000002c: 
                     [0x0000000000001140, 0x0000000000001164): DW_OP_reg5 RDI
                     [0x0000000000001164, 0x0000000000001170): DW_OP_reg4 RSI
                     [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg5 RDI), DW_OP_stack_value)
                  DW_AT_name    ("a1")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

0x0000003b:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x1) loclist = 0x0000003f: 
                     [0x0000000000001140, 0x0000000000001150): DW_OP_reg4 RSI
                     [0x0000000000001150, 0x0000000000001170): DW_OP_reg1 RDX
                     [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value)
                  DW_AT_name    ("a2")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

0x00000044:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x2) loclist = 0x00000052: 
                     [0x0000000000001140, 0x000000000000114e): DW_OP_reg1 RDX
                     [0x000000000000114e, 0x0000000000001170): DW_OP_reg2 RCX
                     [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg1 RDX), DW_OP_stack_value)
                  DW_AT_name    ("a3")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

0x0000004d:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x3) loclist = 0x00000065: 
                     [0x0000000000001140, 0x000000000000114c): DW_OP_reg2 RCX
                     [0x000000000000114c, 0x0000000000001170): DW_OP_reg8 R8
                     [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg2 RCX), DW_OP_stack_value)
                  DW_AT_name    ("a4")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

0x00000056:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x4) loclist = 0x00000078: 
                     [0x0000000000001140, 0x000000000000114a): DW_OP_reg8 R8
                     [0x000000000000114a, 0x0000000000001170): DW_OP_reg9 R9
                     [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg8 R8), DW_OP_stack_value)
                  DW_AT_name    ("a5")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

0x0000005f:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x5) loclist = 0x0000008b: 
                     [0x0000000000001140, 0x0000000000001147): DW_OP_reg9 R9
                     [0x0000000000001147, 0x0000000000001170): DW_OP_reg10 R10
                     [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg9 R9), DW_OP_stack_value)
                  DW_AT_name    ("a6")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

0x00000068:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x6) loclist = 0x0000009e: 
                     [0x0000000000001141, 0x000000000000115d): DW_OP_breg7 RSP+16)
                  DW_AT_name    ("a7")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

0x00000071:     DW_TAG_formal_parameter
                  DW_AT_location        (indexed (0x7) loclist = 0x000000a5: 
                     [0x0000000000001141, 0x000000000000115d): DW_OP_breg7 RSP+24)
                  DW_AT_name    ("a8")
                  DW_AT_decl_file       ("/app/examples/min.c")
                  DW_AT_decl_line       (3)
                  DW_AT_type    (0x000000b0 "int")

Dump of call site:

0x0000008a:     DW_TAG_call_site
                  DW_AT_call_origin     (0x00000027)
                  DW_AT_call_return_pc  (0x00000000000011aa)

0x00000090:       DW_TAG_call_site_parameter
                    DW_AT_location      (DW_OP_reg9 R9)
                    DW_AT_call_value    (DW_OP_lit6)

0x00000095:       DW_TAG_call_site_parameter
                    DW_AT_location      (DW_OP_reg8 R8)
                    DW_AT_call_value    (DW_OP_lit5)

0x0000009a:       DW_TAG_call_site_parameter
                    DW_AT_location      (DW_OP_reg2 RCX)
                    DW_AT_call_value    (DW_OP_lit4)

0x0000009f:       DW_TAG_call_site_parameter
                    DW_AT_location      (DW_OP_reg1 RDX)
                    DW_AT_call_value    (DW_OP_lit3)

0x000000a4:       DW_TAG_call_site_parameter
                    DW_AT_location      (DW_OP_reg4 RSI)
                    DW_AT_call_value    (DW_OP_lit2)

0x000000a9:       DW_TAG_call_site_parameter
                    DW_AT_location      (DW_OP_reg5 RDI)
                    DW_AT_call_value    (DW_OP_lit1)
llvmbot commented 3 months ago

@llvm/issue-subscribers-clang-codegen

Author: Serhii Pievniev (spevnev)

When compiling a C (I haven't tested other languages) function with more than 6 parameters on x86_64 (I haven't tested other architectures), its call_site will have at most 6 parameters, while the rest, which is stored on the stack (their DW_AT_location is DW_OP_fbreg), can only be seen as formal_parameters in the subprogram DIE. I believe that this is a bug, since I can't find anything about this limitation in [DWARF5 format](https://dwarfstd.org/doc/DWARF5.pdf). Minimum example: ```c __attribute__((noinline)) void test(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { printf("%d %d %d %d %d %d %d %d\n", a1, a2, a3, a4, a5, a6, a7, a8); } int main(void) { test(1,2,3,4,5,6,7,8); return 0; } ``` ```console $ clang -O2 -g3 example.c $ llvm-dwarfdump ./a.out ``` DWARF dump of subprogram: ``` 0x00000027: DW_TAG_subprogram DW_AT_low_pc (0x0000000000001140) DW_AT_high_pc (0x0000000000001176) DW_AT_frame_base (DW_OP_reg7 RSP) DW_AT_call_all_calls (true) DW_AT_name ("test") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_prototyped (true) DW_AT_external (true) 0x00000032: DW_TAG_formal_parameter DW_AT_location (indexed (0x0) loclist = 0x0000002c: [0x0000000000001140, 0x0000000000001164): DW_OP_reg5 RDI [0x0000000000001164, 0x0000000000001170): DW_OP_reg4 RSI [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg5 RDI), DW_OP_stack_value) DW_AT_name ("a1") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x0000003b: DW_TAG_formal_parameter DW_AT_location (indexed (0x1) loclist = 0x0000003f: [0x0000000000001140, 0x0000000000001150): DW_OP_reg4 RSI [0x0000000000001150, 0x0000000000001170): DW_OP_reg1 RDX [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value) DW_AT_name ("a2") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000044: DW_TAG_formal_parameter DW_AT_location (indexed (0x2) loclist = 0x00000052: [0x0000000000001140, 0x000000000000114e): DW_OP_reg1 RDX [0x000000000000114e, 0x0000000000001170): DW_OP_reg2 RCX [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg1 RDX), DW_OP_stack_value) DW_AT_name ("a3") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x0000004d: DW_TAG_formal_parameter DW_AT_location (indexed (0x3) loclist = 0x00000065: [0x0000000000001140, 0x000000000000114c): DW_OP_reg2 RCX [0x000000000000114c, 0x0000000000001170): DW_OP_reg8 R8 [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg2 RCX), DW_OP_stack_value) DW_AT_name ("a4") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000056: DW_TAG_formal_parameter DW_AT_location (indexed (0x4) loclist = 0x00000078: [0x0000000000001140, 0x000000000000114a): DW_OP_reg8 R8 [0x000000000000114a, 0x0000000000001170): DW_OP_reg9 R9 [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg8 R8), DW_OP_stack_value) DW_AT_name ("a5") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x0000005f: DW_TAG_formal_parameter DW_AT_location (indexed (0x5) loclist = 0x0000008b: [0x0000000000001140, 0x0000000000001147): DW_OP_reg9 R9 [0x0000000000001147, 0x0000000000001170): DW_OP_reg10 R10 [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg9 R9), DW_OP_stack_value) DW_AT_name ("a6") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000068: DW_TAG_formal_parameter DW_AT_location (indexed (0x6) loclist = 0x0000009e: [0x0000000000001141, 0x000000000000115d): DW_OP_breg7 RSP+16) DW_AT_name ("a7") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000071: DW_TAG_formal_parameter DW_AT_location (indexed (0x7) loclist = 0x000000a5: [0x0000000000001141, 0x000000000000115d): DW_OP_breg7 RSP+24) DW_AT_name ("a8") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") ``` Dump of call site: ``` 0x0000008a: DW_TAG_call_site DW_AT_call_origin (0x00000027) DW_AT_call_return_pc (0x00000000000011aa) 0x00000090: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg9 R9) DW_AT_call_value (DW_OP_lit6) 0x00000095: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg8 R8) DW_AT_call_value (DW_OP_lit5) 0x0000009a: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg2 RCX) DW_AT_call_value (DW_OP_lit4) 0x0000009f: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg1 RDX) DW_AT_call_value (DW_OP_lit3) 0x000000a4: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg4 RSI) DW_AT_call_value (DW_OP_lit2) 0x000000a9: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg5 RDI) DW_AT_call_value (DW_OP_lit1) ```
llvmbot commented 3 months ago

@llvm/issue-subscribers-debuginfo

Author: Serhii Pievniev (spevnev)

When compiling a C (I haven't tested other languages) function with more than 6 parameters on x86_64 (I haven't tested other architectures), its call_site will have at most 6 parameters, while the rest, which is stored on the stack (their DW_AT_location is DW_OP_fbreg), can only be seen as formal_parameters in the subprogram DIE. I believe that this is a bug, since I can't find anything about this limitation in [DWARF5 format](https://dwarfstd.org/doc/DWARF5.pdf). Minimum example: ```c __attribute__((noinline)) void test(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { printf("%d %d %d %d %d %d %d %d\n", a1, a2, a3, a4, a5, a6, a7, a8); } int main(void) { test(1,2,3,4,5,6,7,8); return 0; } ``` ```console $ clang -O2 -g3 example.c $ llvm-dwarfdump ./a.out ``` DWARF dump of subprogram: ``` 0x00000027: DW_TAG_subprogram DW_AT_low_pc (0x0000000000001140) DW_AT_high_pc (0x0000000000001176) DW_AT_frame_base (DW_OP_reg7 RSP) DW_AT_call_all_calls (true) DW_AT_name ("test") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_prototyped (true) DW_AT_external (true) 0x00000032: DW_TAG_formal_parameter DW_AT_location (indexed (0x0) loclist = 0x0000002c: [0x0000000000001140, 0x0000000000001164): DW_OP_reg5 RDI [0x0000000000001164, 0x0000000000001170): DW_OP_reg4 RSI [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg5 RDI), DW_OP_stack_value) DW_AT_name ("a1") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x0000003b: DW_TAG_formal_parameter DW_AT_location (indexed (0x1) loclist = 0x0000003f: [0x0000000000001140, 0x0000000000001150): DW_OP_reg4 RSI [0x0000000000001150, 0x0000000000001170): DW_OP_reg1 RDX [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg4 RSI), DW_OP_stack_value) DW_AT_name ("a2") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000044: DW_TAG_formal_parameter DW_AT_location (indexed (0x2) loclist = 0x00000052: [0x0000000000001140, 0x000000000000114e): DW_OP_reg1 RDX [0x000000000000114e, 0x0000000000001170): DW_OP_reg2 RCX [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg1 RDX), DW_OP_stack_value) DW_AT_name ("a3") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x0000004d: DW_TAG_formal_parameter DW_AT_location (indexed (0x3) loclist = 0x00000065: [0x0000000000001140, 0x000000000000114c): DW_OP_reg2 RCX [0x000000000000114c, 0x0000000000001170): DW_OP_reg8 R8 [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg2 RCX), DW_OP_stack_value) DW_AT_name ("a4") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000056: DW_TAG_formal_parameter DW_AT_location (indexed (0x4) loclist = 0x00000078: [0x0000000000001140, 0x000000000000114a): DW_OP_reg8 R8 [0x000000000000114a, 0x0000000000001170): DW_OP_reg9 R9 [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg8 R8), DW_OP_stack_value) DW_AT_name ("a5") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x0000005f: DW_TAG_formal_parameter DW_AT_location (indexed (0x5) loclist = 0x0000008b: [0x0000000000001140, 0x0000000000001147): DW_OP_reg9 R9 [0x0000000000001147, 0x0000000000001170): DW_OP_reg10 R10 [0x0000000000001170, 0x0000000000001176): DW_OP_entry_value(DW_OP_reg9 R9), DW_OP_stack_value) DW_AT_name ("a6") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000068: DW_TAG_formal_parameter DW_AT_location (indexed (0x6) loclist = 0x0000009e: [0x0000000000001141, 0x000000000000115d): DW_OP_breg7 RSP+16) DW_AT_name ("a7") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") 0x00000071: DW_TAG_formal_parameter DW_AT_location (indexed (0x7) loclist = 0x000000a5: [0x0000000000001141, 0x000000000000115d): DW_OP_breg7 RSP+24) DW_AT_name ("a8") DW_AT_decl_file ("/app/examples/min.c") DW_AT_decl_line (3) DW_AT_type (0x000000b0 "int") ``` Dump of call site: ``` 0x0000008a: DW_TAG_call_site DW_AT_call_origin (0x00000027) DW_AT_call_return_pc (0x00000000000011aa) 0x00000090: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg9 R9) DW_AT_call_value (DW_OP_lit6) 0x00000095: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg8 R8) DW_AT_call_value (DW_OP_lit5) 0x0000009a: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg2 RCX) DW_AT_call_value (DW_OP_lit4) 0x0000009f: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg1 RDX) DW_AT_call_value (DW_OP_lit3) 0x000000a4: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg4 RSI) DW_AT_call_value (DW_OP_lit2) 0x000000a9: DW_TAG_call_site_parameter DW_AT_location (DW_OP_reg5 RDI) DW_AT_call_value (DW_OP_lit1) ```