[PING][PATCH 0/9] Add btf_decl_tag C attribute

2023-09-11 Thread David Faust via Gcc-patches
Ping.

This series adds a new C language attribute for recording additional
information in DWARF and BTF, similar to an existing attribute in clang.

https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624156.html

There are components in c-family, dwarf, ctf and btf.
Thanks.

On 7/11/23 14:57, David Faust via Gcc-patches wrote:
> Hello,
> 
> This series adds support for a new attribute, "btf_decl_tag" in GCC.
> The same attribute is already supported in clang, and is used by various
> components of the BPF ecosystem.
> 
> The purpose of the attribute is to allow to associate (to "tag")
> declarations with arbitrary string annotations, which are emitted into
> debugging information (DWARF and/or BTF) to facilitate post-compilation
> analysis (the motivating use case being the Linux kernel BPF verifier).
> Multiple tags are allowed on the same declaration.
> 
> These strings are not interpreted by the compiler, and the attribute
> itself has no effect on generated code, other than to produce additional
> DWARF DIEs and/or BTF records conveying the annotations.
> 
> This entails:
> 
> - A new C-language-level attribute which allows to associate (to "tag")
>   particular declarations with arbitrary strings.
> 
> - The conveyance of that information in DWARF in the form of a new DIE,
>   DW_TAG_GNU_annotation, with tag number (0x6000) and format matching
>   that of the DW_TAG_LLVM_annotation extension supported in LLVM for
>   the same purpose. These DIEs are already supported by BPF tooling,
>   such as pahole.
> 
> - The conveyance of that information in BTF debug info in the form of
>   BTF_KIND_DECL_TAG records. These records are already supported by
>   LLVM and other tools in the eBPF ecosystem, such as the Linux kernel
>   eBPF verifier.
> 
> 
> Background
> ==
> 
> The purpose of these tags is to convey additional semantic information
> to post-compilation consumers, in particular the Linux kernel eBPF
> verifier. The verifier can make use of that information while analyzing
> a BPF program to aid in determining whether to allow or reject the
> program to be run. More background on these tags can be found in the
> early support for them in the kernel here [1] and [2].
> 
> The "btf_decl_tag" attribute is half the story; the other half is a
> sibling attribute "btf_type_tag" which serves the same purpose but
> applies to types. Support for btf_type_tag will come in a separate
> patch series, since it is impaced by GCC bug 110439 which needs to be
> addressed first.
> 
> I submitted an initial version of this work (including btf_type_tag)
> last spring [3], however at the time there were some open questions
> about the behavior of the btf_type_tag attribute and issues with its
> implementation. Since then we have clarified these details and agreed
> to solutions with the BPF community and LLVM BPF folks.
> 
> The main motivation for emitting the tags in DWARF is that the Linux
> kernel generates its BTF information via pahole, using DWARF as a source:
> 
> ++  BTF  BTF   +--+
> | pahole |---> vmlinux.btf --->| verifier |
> ++ +--+
> ^^
> ||
>   DWARF |BTF |
> ||
>   vmlinux  +-+
>   module1.ko   | BPF program |
>   module2.ko   +-+
> ...
> 
> This is because:
> 
> a)  pahole adds additional kernel-specific information into the
> produced BTF based on additional analysis of kernel objects.
> 
> b)  Unlike GCC, LLVM will only generate BTF for BPF programs.
> 
> b)  GCC can generate BTF for whatever target with -gbtf, but there is no
> support for linking/deduplicating BTF in the linker.
> 
> In the scenario above, the verifier needs access to the pointer tags of
> both the kernel types/declarations (conveyed in the DWARF and translated
> to BTF by pahole) and those of the BPF program (available directly in BTF).
> 
> 
> DWARF Representation
> 
> 
> As noted above, btf_decl_tag is represented in DWARF via a new DIE
> DW_TAG_GNU_annotation, with identical format to the LLVM DWARF
> extension DW_TAG_LLVM_annotation serving the same purpose. The DIE has
> the following format:
> 
>   DW_TAG_GNU_annotation (0x6000)
> DW_AT_name: "btf_decl_tag"
> DW_AT_const_value: 
> 
> These DIEs are placed in the DWARF tree as ch

[PATCH] bpf: neg instruction does not accept an immediate

2023-08-21 Thread David Faust via Gcc-patches
The BPF virtual machine does not support neg nor neg32 instructions with
an immediate.

The erroneous instructions were removed from binutils:
https://sourceware.org/pipermail/binutils/2023-August/129135.html

Change the define_insn so that an immediate cannot be accepted.

>From testing, a neg-immediate was probably never chosen over a
mov-immediate anyway.

Tested on x86_64-linux-gnu host for bpf-unknown-none target.

gcc/

* config/bpf/bpf.md (neg): Second operand must be a register.
---
 gcc/config/bpf/bpf.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index a64de1095ed..e87d72182bb 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -163,8 +163,8 @@ (define_insn "sub3"
 
 ;;; Negation
 (define_insn "neg2"
-  [(set (match_operand:AM 0 "register_operand"   "=r,r")
-(neg:AM (match_operand:AM 1 "reg_or_imm_operand" " 0,I")))]
+  [(set (match_operand:AM 0 "register_operand" "=r")
+(neg:AM (match_operand:AM 1 "register_operand" " 0")))]
   ""
   "{neg\t%0|%w0 = -%w1}"
   [(set_attr "type" "")])
-- 
2.40.1



[PATCH] bpf: remove useless define_insn for extendsisi2

2023-08-15 Thread David Faust via Gcc-patches
This define_insn is never used, since a sign-extend to the same mode is
just a move, so delete it.

Tested on x86_64-linux-gnu host for bpf-unknown-none target.

gcc/

* config/bpf/bpf.md (extendsisi2): Delete useless define_insn.
---
 gcc/config/bpf/bpf.md | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index e0a42b9f939..a64de1095ed 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -350,13 +350,6 @@ (define_insn "extendqidi2"
{ldxsb\t%0,%1|%0 = *(s8 *) (%1)}"
   [(set_attr "type" "alu,ldx")])
 
-(define_insn "extendsisi2"
-  [(set (match_operand:SI 0 "register_operand" "=r")
-(sign_extend:SI (match_operand:SI 1 "register_operand" "r")))]
-  "bpf_has_smov"
-  "{movs32\t%0,%1,32|%w0 = (s32) %w1}"
-  [(set_attr "type" "alu")])
-
 (define_insn "extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "=r")
 (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
-- 
2.40.1



[PATCH] bpf: fix pseudoc w regs for small modes [PR111029]

2023-08-15 Thread David Faust via Gcc-patches
In the BPF pseudo-c assembly dialect, registers treated as 32-bits
rather than the full 64 in various instructions ought to be printed as
"wN" rather than "rN".  But bpf_print_register () was only doing this
for specifically SImode registers, meaning smaller modes were printed
incorrectly.

This caused assembler errors like:

  Error: unrecognized instruction `w2 =(s8)r1'

for a 32-bit sign-extending register move instruction, where the source
register is used in QImode.

Fix bpf_print_register () to print the "w" version of register when
specified by the template for any mode 32-bits or smaller.

Tested on bpf-unknown-none.

PR target/111029

gcc/
* config/bpf/bpf.cc (bpf_print_register): Print 'w' registers
for any mode 32-bits or smaller, not just SImode.

gcc/testsuite/

* gcc.target/bpf/smov-2.c: New test.
* gcc.target/bpf/smov-pseudoc-2.c: New test.
---
 gcc/config/bpf/bpf.cc |  2 +-
 gcc/testsuite/gcc.target/bpf/smov-2.c | 15 +++
 gcc/testsuite/gcc.target/bpf/smov-pseudoc-2.c | 15 +++
 3 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/smov-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/smov-pseudoc-2.c

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 3516b79bce4..1d0abd7fbb3 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -753,7 +753,7 @@ bpf_print_register (FILE *file, rtx op, int code)
 fprintf (file, "%s", reg_names[REGNO (op)]);
   else
 {
-  if (code == 'w' && GET_MODE (op) == SImode)
+  if (code == 'w' && GET_MODE_SIZE (GET_MODE (op)) <= 4)
{
  if (REGNO (op) == BPF_FP)
fprintf (file, "w10");
diff --git a/gcc/testsuite/gcc.target/bpf/smov-2.c 
b/gcc/testsuite/gcc.target/bpf/smov-2.c
new file mode 100644
index 000..6f3516d2385
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/smov-2.c
@@ -0,0 +1,15 @@
+/* Check signed 32-bit mov instructions.  */
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v4 -O2" } */
+
+int
+foo (unsigned char a, unsigned short b)
+{
+  int x = (char) a;
+  int y = (short) b;
+
+  return x + y;
+}
+
+/* { dg-final { scan-assembler {movs32\t%r.,%r.,8\n} } } */
+/* { dg-final { scan-assembler {movs32\t%r.,%r.,16\n} } } */
diff --git a/gcc/testsuite/gcc.target/bpf/smov-pseudoc-2.c 
b/gcc/testsuite/gcc.target/bpf/smov-pseudoc-2.c
new file mode 100644
index 000..6af6cadf8df
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/smov-pseudoc-2.c
@@ -0,0 +1,15 @@
+/* Check signed 32-bit mov instructions (pseudo-C asm dialect).  */
+/* { dg-do compile } */
+/* { dg-options "-mcpu=v4 -O2 -masm=pseudoc" } */
+
+int
+foo (unsigned char a, unsigned short b)
+{
+  int x = (char) a;
+  int y = (short) b;
+
+  return x + y;
+}
+
+/* { dg-final { scan-assembler {w. = \(s8\) w.\n} } } */
+/* { dg-final { scan-assembler {w. = \(s16\) w.\n} } } */
-- 
2.40.1



[PING 2][PATCH 0/9] Add btf_decl_tag C attribute

2023-08-09 Thread David Faust via Gcc-patches
Ping for this series.

https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624156.html

Thanks

On 7/11/23 14:57, David Faust via Gcc-patches wrote:
> Hello,
> 
> This series adds support for a new attribute, "btf_decl_tag" in GCC.
> The same attribute is already supported in clang, and is used by various
> components of the BPF ecosystem.
> 
> The purpose of the attribute is to allow to associate (to "tag")
> declarations with arbitrary string annotations, which are emitted into
> debugging information (DWARF and/or BTF) to facilitate post-compilation
> analysis (the motivating use case being the Linux kernel BPF verifier).
> Multiple tags are allowed on the same declaration.
> 
> These strings are not interpreted by the compiler, and the attribute
> itself has no effect on generated code, other than to produce additional
> DWARF DIEs and/or BTF records conveying the annotations.
> 
> This entails:
> 
> - A new C-language-level attribute which allows to associate (to "tag")
>   particular declarations with arbitrary strings.
> 
> - The conveyance of that information in DWARF in the form of a new DIE,
>   DW_TAG_GNU_annotation, with tag number (0x6000) and format matching
>   that of the DW_TAG_LLVM_annotation extension supported in LLVM for
>   the same purpose. These DIEs are already supported by BPF tooling,
>   such as pahole.
> 
> - The conveyance of that information in BTF debug info in the form of
>   BTF_KIND_DECL_TAG records. These records are already supported by
>   LLVM and other tools in the eBPF ecosystem, such as the Linux kernel
>   eBPF verifier.
> 
> 
> Background
> ==
> 
> The purpose of these tags is to convey additional semantic information
> to post-compilation consumers, in particular the Linux kernel eBPF
> verifier. The verifier can make use of that information while analyzing
> a BPF program to aid in determining whether to allow or reject the
> program to be run. More background on these tags can be found in the
> early support for them in the kernel here [1] and [2].
> 
> The "btf_decl_tag" attribute is half the story; the other half is a
> sibling attribute "btf_type_tag" which serves the same purpose but
> applies to types. Support for btf_type_tag will come in a separate
> patch series, since it is impaced by GCC bug 110439 which needs to be
> addressed first.
> 
> I submitted an initial version of this work (including btf_type_tag)
> last spring [3], however at the time there were some open questions
> about the behavior of the btf_type_tag attribute and issues with its
> implementation. Since then we have clarified these details and agreed
> to solutions with the BPF community and LLVM BPF folks.
> 
> The main motivation for emitting the tags in DWARF is that the Linux
> kernel generates its BTF information via pahole, using DWARF as a source:
> 
> ++  BTF  BTF   +--+
> | pahole |---> vmlinux.btf --->| verifier |
> ++ +--+
> ^^
> ||
>   DWARF |BTF |
> ||
>   vmlinux  +-+
>   module1.ko   | BPF program |
>   module2.ko   +-+
> ...
> 
> This is because:
> 
> a)  pahole adds additional kernel-specific information into the
> produced BTF based on additional analysis of kernel objects.
> 
> b)  Unlike GCC, LLVM will only generate BTF for BPF programs.
> 
> b)  GCC can generate BTF for whatever target with -gbtf, but there is no
> support for linking/deduplicating BTF in the linker.
> 
> In the scenario above, the verifier needs access to the pointer tags of
> both the kernel types/declarations (conveyed in the DWARF and translated
> to BTF by pahole) and those of the BPF program (available directly in BTF).
> 
> 
> DWARF Representation
> 
> 
> As noted above, btf_decl_tag is represented in DWARF via a new DIE
> DW_TAG_GNU_annotation, with identical format to the LLVM DWARF
> extension DW_TAG_LLVM_annotation serving the same purpose. The DIE has
> the following format:
> 
>   DW_TAG_GNU_annotation (0x6000)
> DW_AT_name: "btf_decl_tag"
> DW_AT_const_value: 
> 
> These DIEs are placed in the DWARF tree as children of the DIE for the
> appropriate declaration, and one such DIE is created for each occurrence
> of the btf_decl_tag attribute on a declaration.
> 
> For example:
> 
>

[COMMITTED] MAINTAINERS: Add myself as a BPF port reviewer

2023-08-07 Thread David Faust via Gcc-patches
ChangeLog:

* MAINTAINERS: Add the BPF port to my reviewer listing.
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 6cac5ac6671..1e54844c905 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -273,7 +273,7 @@ arc portClaudiu Zissulescu  

 callgraph  Martin Jambor   
 C front endMarek Polacek   
 CTF, BTF   Indu Bhagat 
-CTF, BTF   David Faust 
+CTF, BTF, bpf port David Faust 
 dataflow   Paolo Bonzini   
 dataflow   Seongbae Park   
 dataflow   Kenneth Zadeck  
-- 
2.40.1



Re: [PATCH] bpf: ISA V4 sign-extending move and load insns [PR110782,PR110784]

2023-07-27 Thread David Faust via Gcc-patches



On 7/27/23 15:27, Jose E. Marchesi wrote:
> 
> Hi David.
> Thanks for the patch.
> 
>> BPF ISA V4 introduces sign-extending move and load operations.  This
>> patch makes the BPF backend generate those instructions, when enabled
>> and useful.
>>
>> A new option, -m[no-]smov gates generation of these instructions, and is
>> enabled by default for -mcpu=v4 and above.  Tests for the new
>> instructions and documentation for the new options are included.
>>
>> Tested on bpf-unknown-none.
>> OK?
>>
>> gcc/
>>
>>  * config/bpf/bpf.opt (msmov): New option.
>>  * config/bpf/bpf.cc (bpf_option_override): Handle it here.
>>  * config/bpf/bpf.md (*extendsidi2): New.
>>  (extendhidi2): New.
>>  (extendqidi2): New.
>>  (extendsisi2): New.
>>  (extendhisi2): New.
>>  (extendqisi2): New.
>>  * doc/invoke.texi (Option Summary): Add -msmov eBPF option.
>>  (eBPF Options): Add -m[no-]smov.  Document that -mcpu=v4
>>  also enables -msmov.
>>
>> gcc/testsuite/
>>
>>  * gcc.target/bpf/sload-1.c: New test.
>>  * gcc.target/bpf/sload-pseudoc-1.c: New test.
>>  * gcc.target/bpf/smov-1.c: New test.
>>  * gcc.target/bpf/smov-pseudoc-1.c: New test.
> 
> Looks like you forgot to mention the bugzilla PR in the changelog
> entries.  Would be nice to have them there so automatic updates happen
> in the bugzillas.

Good catch, thanks!

> 
> Other than that, OK.
> Thanks!

Pushed, with PRs added in the changelog and a tiny reword to the doc below.

> 
>> ---
>>  gcc/config/bpf/bpf.cc |  3 ++
>>  gcc/config/bpf/bpf.md | 50 +++
>>  gcc/config/bpf/bpf.opt|  4 ++
>>  gcc/doc/invoke.texi   |  9 +++-
>>  gcc/testsuite/gcc.target/bpf/sload-1.c| 16 ++
>>  .../gcc.target/bpf/sload-pseudoc-1.c  | 16 ++
>>  gcc/testsuite/gcc.target/bpf/smov-1.c | 18 +++
>>  gcc/testsuite/gcc.target/bpf/smov-pseudoc-1.c | 18 +++
>>  8 files changed, 133 insertions(+), 1 deletion(-)
>>  create mode 100644 gcc/testsuite/gcc.target/bpf/sload-1.c
>>  create mode 100644 gcc/testsuite/gcc.target/bpf/sload-pseudoc-1.c
>>  create mode 100644 gcc/testsuite/gcc.target/bpf/smov-1.c
>>  create mode 100644 gcc/testsuite/gcc.target/bpf/smov-pseudoc-1.c
>>
>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>> index 0e07b416add..b5b5674edbb 100644
>> --- a/gcc/config/bpf/bpf.cc
>> +++ b/gcc/config/bpf/bpf.cc
>> @@ -262,6 +262,9 @@ bpf_option_override (void)
>>if (bpf_has_sdiv == -1)
>>  bpf_has_sdiv = (bpf_isa >= ISA_V4);
>>  
>> +  if (bpf_has_smov == -1)
>> +bpf_has_smov = (bpf_isa >= ISA_V4);
>> +
>>/* Disable -fstack-protector as it is not supported in BPF.  */
>>if (flag_stack_protect)
>>  {
>> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
>> index 66436397bb7..a69a239b9d6 100644
>> --- a/gcc/config/bpf/bpf.md
>> +++ b/gcc/config/bpf/bpf.md
>> @@ -307,6 +307,56 @@ (define_expand "extendsidi2"
>>DONE;
>>  })
>>  
>> +;; ISA V4 introduces sign-extending move and load operations.
>> +
>> +(define_insn "*extendsidi2"
>> +  [(set (match_operand:DI 0 "register_operand" "=r,r")
>> +(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
>> +  "bpf_has_smov"
>> +  "@
>> +   {movs\t%0,%1,32|%0 = (s32) %1}
>> +   {ldxsw\t%0,%1|%0 = *(s32 *) (%1)}"
>> +  [(set_attr "type" "alu,ldx")])
>> +
>> +(define_insn "extendhidi2"
>> +  [(set (match_operand:DI 0 "register_operand" "=r,r")
>> +(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,q")))]
>> +  "bpf_has_smov"
>> +  "@
>> +   {movs\t%0,%1,16|%0 = (s16) %1}
>> +   {ldxsh\t%0,%1|%0 = *(s16 *) (%1)}"
>> +  [(set_attr "type" "alu,ldx")])
>> +
>> +(define_insn "extendqidi2"
>> +  [(set (match_operand:DI 0 "register_operand" "=r,r")
>> +(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,q")))]
>> +  "bpf_has_smov"
>> +  "@
>> +   {movs\t%0,%1,8|%0 = (s8) %1}
>> +   {ldxsb\t%0,%1|%0 = *(s8 *) (%1)}"
>> +  [(set_attr "type" "alu,ldx")])
>> +
>> +(define_insn "extendsisi2"
>> +  [(set (match_operand:SI 0 "register_operand" "=r")
>> +(sign_extend:SI (match_operand:SI 1 "register_operand" "r")))]
>> +  "bpf_has_smov"
>> +  "{movs32\t%0,%1,32|%w0 = (s32) %w1}"
>> +  [(set_attr "type" "alu")])
>> +
>> +(define_insn "extendhisi2"
>> +  [(set (match_operand:SI 0 "register_operand" "=r")
>> +(sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
>> +  "bpf_has_smov"
>> +  "{movs32\t%0,%1,16|%w0 = (s16) %w1}"
>> +  [(set_attr "type" "alu")])
>> +
>> +(define_insn "extendqisi2"
>> +  [(set (match_operand:SI 0 "register_operand" "=r")
>> +(sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
>> +  "bpf_has_smov"
>> +  "{movs32\t%0,%1,8|%w0 = (s8) %w1}"
>> +  [(set_attr "type" "alu")])
>> +
>>   Data movement
>>  
>>  (define_mode_iterator MM [QI HI SI DI SF DF])
>> diff --git a/gcc/config/bpf/

[PATCH] bpf: ISA V4 sign-extending move and load insns [PR110782, PR110784]

2023-07-27 Thread David Faust via Gcc-patches
BPF ISA V4 introduces sign-extending move and load operations.  This
patch makes the BPF backend generate those instructions, when enabled
and useful.

A new option, -m[no-]smov gates generation of these instructions, and is
enabled by default for -mcpu=v4 and above.  Tests for the new
instructions and documentation for the new options are included.

Tested on bpf-unknown-none.
OK?

gcc/

* config/bpf/bpf.opt (msmov): New option.
* config/bpf/bpf.cc (bpf_option_override): Handle it here.
* config/bpf/bpf.md (*extendsidi2): New.
(extendhidi2): New.
(extendqidi2): New.
(extendsisi2): New.
(extendhisi2): New.
(extendqisi2): New.
* doc/invoke.texi (Option Summary): Add -msmov eBPF option.
(eBPF Options): Add -m[no-]smov.  Document that -mcpu=v4
also enables -msmov.

gcc/testsuite/

* gcc.target/bpf/sload-1.c: New test.
* gcc.target/bpf/sload-pseudoc-1.c: New test.
* gcc.target/bpf/smov-1.c: New test.
* gcc.target/bpf/smov-pseudoc-1.c: New test.
---
 gcc/config/bpf/bpf.cc |  3 ++
 gcc/config/bpf/bpf.md | 50 +++
 gcc/config/bpf/bpf.opt|  4 ++
 gcc/doc/invoke.texi   |  9 +++-
 gcc/testsuite/gcc.target/bpf/sload-1.c| 16 ++
 .../gcc.target/bpf/sload-pseudoc-1.c  | 16 ++
 gcc/testsuite/gcc.target/bpf/smov-1.c | 18 +++
 gcc/testsuite/gcc.target/bpf/smov-pseudoc-1.c | 18 +++
 8 files changed, 133 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/sload-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/sload-pseudoc-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/smov-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/smov-pseudoc-1.c

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 0e07b416add..b5b5674edbb 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -262,6 +262,9 @@ bpf_option_override (void)
   if (bpf_has_sdiv == -1)
 bpf_has_sdiv = (bpf_isa >= ISA_V4);
 
+  if (bpf_has_smov == -1)
+bpf_has_smov = (bpf_isa >= ISA_V4);
+
   /* Disable -fstack-protector as it is not supported in BPF.  */
   if (flag_stack_protect)
 {
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 66436397bb7..a69a239b9d6 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -307,6 +307,56 @@ (define_expand "extendsidi2"
   DONE;
 })
 
+;; ISA V4 introduces sign-extending move and load operations.
+
+(define_insn "*extendsidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
+  "bpf_has_smov"
+  "@
+   {movs\t%0,%1,32|%0 = (s32) %1}
+   {ldxsw\t%0,%1|%0 = *(s32 *) (%1)}"
+  [(set_attr "type" "alu,ldx")])
+
+(define_insn "extendhidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,q")))]
+  "bpf_has_smov"
+  "@
+   {movs\t%0,%1,16|%0 = (s16) %1}
+   {ldxsh\t%0,%1|%0 = *(s16 *) (%1)}"
+  [(set_attr "type" "alu,ldx")])
+
+(define_insn "extendqidi2"
+  [(set (match_operand:DI 0 "register_operand" "=r,r")
+(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,q")))]
+  "bpf_has_smov"
+  "@
+   {movs\t%0,%1,8|%0 = (s8) %1}
+   {ldxsb\t%0,%1|%0 = *(s8 *) (%1)}"
+  [(set_attr "type" "alu,ldx")])
+
+(define_insn "extendsisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+(sign_extend:SI (match_operand:SI 1 "register_operand" "r")))]
+  "bpf_has_smov"
+  "{movs32\t%0,%1,32|%w0 = (s32) %w1}"
+  [(set_attr "type" "alu")])
+
+(define_insn "extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+(sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
+  "bpf_has_smov"
+  "{movs32\t%0,%1,16|%w0 = (s16) %w1}"
+  [(set_attr "type" "alu")])
+
+(define_insn "extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+(sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
+  "bpf_has_smov"
+  "{movs32\t%0,%1,8|%w0 = (s8) %w1}"
+  [(set_attr "type" "alu")])
+
  Data movement
 
 (define_mode_iterator MM [QI HI SI DI SF DF])
diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt
index b21cfcab9ea..8e240d397e4 100644
--- a/gcc/config/bpf/bpf.opt
+++ b/gcc/config/bpf/bpf.opt
@@ -71,6 +71,10 @@ msdiv
 Target Var(bpf_has_sdiv) Init(-1)
 Enable signed division and modulus instructions.
 
+msmov
+Target Var(bpf_has_smov) Init(-1)
+Enable signed move and memory load instructions.
+
 mcpu=
 Target RejectNegative Joined Var(bpf_isa) Enum(bpf_isa) Init(ISA_V4)
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 91113dd5821..e574acfd612 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -947,7 +947,7 @@ Objective-C and Objective-C++ Dialects}.
 @emph{eBPF Options}
 @gccoptlist{-mbig-endian -mlittle-endian
 -mframe-limit=@var{b

[PATCH] bpf: minor doc cleanup for command-line options

2023-07-27 Thread David Faust via Gcc-patches
This patch makes some minor cleanups to eBPF options documented in
invoke.texi:
 - Delete some vestigal docs for removed -mkernel option
 - Add -mbswap and -msdiv to the option summary
 - Note the negative versions of several options
 - Note that -mcpu=v4 also enables -msdiv.

gcc/

* doc/invoke.texi (Option Summary): Remove -mkernel eBPF option.
Add -mbswap and -msdiv eBPF options.
(eBPF Options): Remove -mkernel.  Add -mno-{jmpext, jmp32,
alu32, v3-atomics, bswap, sdiv}.  Document that -mcpu=v4 also
enables -msdiv.
---
 gcc/doc/invoke.texi | 48 ++---
 1 file changed, 23 insertions(+), 25 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e0fd7bd5b72..91113dd5821 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -945,9 +945,10 @@ Objective-C and Objective-C++ Dialects}.
 -mmemory-latency=@var{time}}
 
 @emph{eBPF Options}
-@gccoptlist{-mbig-endian -mlittle-endian -mkernel=@var{version}
+@gccoptlist{-mbig-endian -mlittle-endian
 -mframe-limit=@var{bytes} -mxbpf -mco-re -mno-co-re -mjmpext
--mjmp32 -malu32 -mv3-atomics -mcpu=@var{version} -masm=@var{dialect}}
+-mjmp32 -malu32 -mv3-atomics -mbswap -msdiv -mcpu=@var{version}
+-masm=@var{dialect}}
 
 @emph{FR30 Options}
 @gccoptlist{-msmall-model  -mno-lsim}
@@ -24674,18 +24675,6 @@ the value that can be specified should be less than or 
equal to
 @samp{32767}.  Defaults to whatever limit is imposed by the version of
 the Linux kernel targeted.
 
-@opindex mkernel
-@item -mkernel=@var{version}
-This specifies the minimum version of the kernel that will run the
-compiled program.  GCC uses this version to determine which
-instructions to use, what kernel helpers to allow, etc.  Currently,
-@var{version} can be one of @samp{4.0}, @samp{4.1}, @samp{4.2},
-@samp{4.3}, @samp{4.4}, @samp{4.5}, @samp{4.6}, @samp{4.7},
-@samp{4.8}, @samp{4.9}, @samp{4.10}, @samp{4.11}, @samp{4.12},
-@samp{4.13}, @samp{4.14}, @samp{4.15}, @samp{4.16}, @samp{4.17},
-@samp{4.18}, @samp{4.19}, @samp{4.20}, @samp{5.0}, @samp{5.1},
-@samp{5.2}, @samp{latest} and @samp{native}.
-
 @opindex mbig-endian
 @item -mbig-endian
 Generate code for a big-endian target.
@@ -24696,30 +24685,38 @@ Generate code for a little-endian target.  This is 
the default.
 
 @opindex mjmpext
 @item -mjmpext
-Enable generation of extra conditional-branch instructions.
+@itemx -mno-jmpext
+Enable or disable generation of extra conditional-branch instructions.
 Enabled for CPU v2 and above.
 
 @opindex mjmp32
 @item -mjmp32
-Enable 32-bit jump instructions. Enabled for CPU v3 and above.
+@itemx -mno-jmp32
+Enable or disable generation of 32-bit jump instructions.
+Enabled for CPU v3 and above.
 
 @opindex malu32
 @item -malu32
-Enable 32-bit ALU instructions. Enabled for CPU v3 and above.
+@itemx -mno-alu32
+Enable or disable generation of 32-bit ALU instructions.
+Enabled for CPU v3 and above.
+
+@opindex mv3-atomics
+@item -mv3-atomics
+@itemx -mno-v3-atomics
+Enable or disable instructions for general atomic operations introduced
+in CPU v3.  Enabled for CPU v3 and above.
 
 @opindex mbswap
 @item -mbswap
-Enable byte swap instructions.  Enabled for CPU v4 and above.
+@itemx -mno-bswap
+Enable or disable byte swap instructions.  Enabled for CPU v4 and above.
 
 @opindex msdiv
 @item -msdiv
-Enable signed division and modulus instructions.  Enabled for CPU v4
-and above.
-
-@opindex mv3-atomics
-@item -mv3-atomics
-Enable instructions for general atomic operations introduced in CPU v3.
-Enabled for CPU v3 and above.
+@itemx -mno-sdiv
+Enable or disable signed division and modulus instructions.  Enabled for
+CPU v4 and above.
 
 @opindex mcpu
 @item -mcpu=@var{version}
@@ -24747,6 +24744,7 @@ All features of v2, plus:
 All features of v3, plus:
 @itemize @minus
 @item Byte swap instructions, as in @option{-mbswap}
+@item Signed division and modulus instructions, as in @option{-msdiv}
 @end itemize
 @end table
 
-- 
2.40.1



[PATCH] bpf: correct pseudo-C template for add3 and sub3

2023-07-27 Thread David Faust via Gcc-patches
The pseudo-C output templates for these instructions were incorrectly
using operand 1 rather than operand 2 on the RHS, which led to some
very incorrect assembly generation with -masm=pseudoc.

Tested on bpf-unknown-none.
OK?

gcc/

* config/bpf/bpf.md (add3): Use %w2 instead of %w1
in pseudo-C dialect output template.
(sub3): Likewise.

gcc/testsuite/

* gcc.target/bpf/alu-2.c: New test.
* gcc.target/bpf/alu-pseudoc-2.c: Likewise.
---
 gcc/config/bpf/bpf.md|  4 ++--
 gcc/testsuite/gcc.target/bpf/alu-2.c | 12 
 gcc/testsuite/gcc.target/bpf/alu-pseudoc-2.c | 13 +
 3 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/alu-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/alu-pseudoc-2.c

diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 2ffc4ebd17e..66436397bb7 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -131,7 +131,7 @@ (define_insn "add3"
 (plus:AM (match_operand:AM 1 "register_operand"   " 0,0")
  (match_operand:AM 2 "reg_or_imm_operand" " r,I")))]
   "1"
-  "{add\t%0,%2|%w0 += %w1}"
+  "{add\t%0,%2|%w0 += %w2}"
   [(set_attr "type" "")])
 
 ;;; Subtraction
@@ -144,7 +144,7 @@ (define_insn "sub3"
 (minus:AM (match_operand:AM 1 "register_operand" " 0")
   (match_operand:AM 2 "register_operand" " r")))]
   ""
-  "{sub\t%0,%2|%w0 -= %w1}"
+  "{sub\t%0,%2|%w0 -= %w2}"
   [(set_attr "type" "")])
 
 ;;; Negation
diff --git a/gcc/testsuite/gcc.target/bpf/alu-2.c 
b/gcc/testsuite/gcc.target/bpf/alu-2.c
new file mode 100644
index 000..0444a9bc68a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/alu-2.c
@@ -0,0 +1,12 @@
+/* Check add and sub instructions.  */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+long foo (long x, long y)
+{
+  return y - x + 4;
+}
+
+/* { dg-final { scan-assembler-not {sub\t(%r.),\1\n} } } */
+/* { dg-final { scan-assembler {sub\t(\%r.),(\%r.)\n} } } */
+/* { dg-final { scan-assembler {add\t(\%r.),4\n} } } */
diff --git a/gcc/testsuite/gcc.target/bpf/alu-pseudoc-2.c 
b/gcc/testsuite/gcc.target/bpf/alu-pseudoc-2.c
new file mode 100644
index 000..751db2477c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/alu-pseudoc-2.c
@@ -0,0 +1,13 @@
+/* Check add and sub instructions (pseudoc asm dialect).  */
+/* { dg-do compile } */
+/* { dg-options "-masm=pseudoc" } */
+
+long foo (long x, long y)
+{
+  return y - x + 4;
+}
+
+/* { dg-final { scan-assembler-not {\t(r.) -= \1\n} } } */
+/* { dg-final { scan-assembler {\t(r.) -= (r.)\n} } } */
+/* { dg-final { scan-assembler {\t(r.) \+= 4\n} } } */
+
-- 
2.40.1



[COMMITTED v2 1/2] bpf: don't print () in bpf_print_operand_address

2023-07-25 Thread David Faust via Gcc-patches
[Changes from v1: save calls to fprintf]

Unfortunately, the pseudo-C dialect syntax used for some of the v3
atomic instructions clashes with unconditionally printing the
surrounding parentheses in bpf_print_operand_address.

Instead, place the parentheses in the output templates where needed.

gcc/

* config/bpf/bpf.cc (bpf_print_operand_address): Don't print
enclosing parentheses for pseudo-C dialect.
* config/bpf/bpf.md (zero_exdendhidi2): Add parentheses around
operands of pseudo-C dialect output templates where needed.
(zero_extendqidi2): Likewise.
(zero_extendsidi2): Likewise.
(*mov): Likewise.
---
 gcc/config/bpf/bpf.cc | 11 +++
 gcc/config/bpf/bpf.md | 12 ++--
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 55b6927a62f..2e1e3e3abcf 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -933,9 +933,10 @@ bpf_print_operand_address (FILE *file, rtx addr)
   switch (GET_CODE (addr))
 {
 case REG:
-  fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+  if (asm_dialect == ASM_NORMAL)
+   fprintf (file, "[");
   bpf_print_register (file, addr, 0);
-  fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0)");
+  fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0");
   break;
 case PLUS:
   {
@@ -944,11 +945,13 @@ bpf_print_operand_address (FILE *file, rtx addr)
 
if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
  {
-   fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+   if (asm_dialect == ASM_NORMAL)
+ fprintf (file, "[");
bpf_print_register (file, op0, 0);
fprintf (file, "+");
output_addr_const (file, op1);
-   fprintf (file, asm_dialect == ASM_NORMAL ? "]" : ")");
+   if (asm_dialect == ASM_NORMAL)
+ fprintf (file, "]");
  }
else
  fatal_insn ("invalid address in operand", addr);
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 64342ea1de2..579a8213b09 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -260,7 +260,7 @@ (define_insn "zero_extendhidi2"
   "@
{and\t%0,0x|%0 &= 0x}
{mov\t%0,%1\;and\t%0,0x|%0 = %1;%0 &= 0x}
-   {ldxh\t%0,%1|%0 = *(u16 *) %1}"
+   {ldxh\t%0,%1|%0 = *(u16 *) (%1)}"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendqidi2"
@@ -270,7 +270,7 @@ (define_insn "zero_extendqidi2"
   "@
{and\t%0,0xff|%0 &= 0xff}
{mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}
-   {ldxh\t%0,%1|%0 = *(u8 *) %1}"
+   {ldxh\t%0,%1|%0 = *(u8 *) (%1)}"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendsidi2"
@@ -280,7 +280,7 @@ (define_insn "zero_extendsidi2"
   ""
   "@
* return bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : 
\"{mov\t%0,%1\;and\t%0,0x|%0 = %1;%0 &= 0x}\";
-   {ldxw\t%0,%1|%0 = *(u32 *) %1}"
+   {ldxw\t%0,%1|%0 = *(u32 *) (%1)}"
   [(set_attr "type" "alu,ldx")])
 
 ;;; Sign-extension
@@ -319,11 +319,11 @@ (define_insn "*mov"
 (match_operand:MM 1 "mov_src_operand"  " q,rI,B,r,I"))]
   ""
   "@
-   {ldx\t%0,%1|%0 = *( *) %1}
+   {ldx\t%0,%1|%0 = *( *) (%1)}
{mov\t%0,%1|%0 = %1}
{lddw\t%0,%1|%0 = %1 ll}
-   {stx\t%0,%1|*( *) %0 = %1}
-   {st\t%0,%1|*( *) %0 = %1}"
+   {stx\t%0,%1|*( *) (%0) = %1}
+   {st\t%0,%1|*( *) (%0) = %1}"
 [(set_attr "type" "ldx,alu,alu,stx,st")])
 
  Shifts
-- 
2.40.1



[PATCH v2 2/2] bpf: add v3 atomic instructions

2023-07-25 Thread David Faust via Gcc-patches
[Changes from v1: fix merge issue in invoke.texi]

This patch adds support for the general atomic operations introduced in
eBPF v3. In addition to the existing atomic add instruction, this adds:
 - Atomic and, or, xor
 - Fetching versions of these operations (including add)
 - Atomic exchange
 - Atomic compare-and-exchange

To control emission of these instructions, a new target option
-m[no-]v3-atomics is added. This option is enabled by -mcpu=v3
and above.

Support for these instructions was recently added in binutils.

gcc/

* config/bpf/bpf.opt (mv3-atomics): New option.
* config/bpf/bpf.cc (bpf_option_override): Handle it here.
* config/bpf/bpf.h (enum_reg_class): Add R0 class.
(REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS): Likewise.
(REGNO_REG_CLASS): Handle R0.
* config/bpf/bpf.md (UNSPEC_XADD): Rename to UNSPEC_AADD.
(UNSPEC_AAND): New unspec.
(UNSPEC_AOR): Likewise.
(UNSPEC_AXOR): Likewise.
(UNSPEC_AFADD): Likewise.
(UNSPEC_AFAND): Likewise.
(UNSPEC_AFOR): Likewise.
(UNSPEC_AFXOR): Likewise.
(UNSPEC_AXCHG): Likewise.
(UNSPEC_ACMPX): Likewise.
(atomic_add): Use UNSPEC_AADD and atomic type attribute.
Move to...
* config/bpf/atomic.md: ...Here. New file.
* config/bpf/constraints.md (t): New constraint for R0.
* doc/invoke.texi (eBPF Options): Document -mv3-atomics.

gcc/testsuite/

* gcc.target/bpf/atomic-cmpxchg-1.c: New test.
* gcc.target/bpf/atomic-cmpxchg-2.c: New test.
* gcc.target/bpf/atomic-fetch-op-1.c: New test.
* gcc.target/bpf/atomic-fetch-op-2.c: New test.
* gcc.target/bpf/atomic-fetch-op-3.c: New test.
* gcc.target/bpf/atomic-op-1.c: New test.
* gcc.target/bpf/atomic-op-2.c: New test.
* gcc.target/bpf/atomic-op-3.c: New test.
* gcc.target/bpf/atomic-xchg-1.c: New test.
* gcc.target/bpf/atomic-xchg-2.c: New test.
---
 gcc/config/bpf/atomic.md  | 185 ++
 gcc/config/bpf/bpf.cc |   3 +
 gcc/config/bpf/bpf.h  |   6 +-
 gcc/config/bpf/bpf.md |  29 ++-
 gcc/config/bpf/bpf.opt|   4 +
 gcc/config/bpf/constraints.md |   3 +
 gcc/doc/invoke.texi   |   8 +-
 .../gcc.target/bpf/atomic-cmpxchg-1.c |  19 ++
 .../gcc.target/bpf/atomic-cmpxchg-2.c |  19 ++
 .../gcc.target/bpf/atomic-fetch-op-1.c|  50 +
 .../gcc.target/bpf/atomic-fetch-op-2.c|  50 +
 .../gcc.target/bpf/atomic-fetch-op-3.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-op-1.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-op-2.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-op-3.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-xchg-1.c  |  20 ++
 gcc/testsuite/gcc.target/bpf/atomic-xchg-2.c  |  20 ++
 17 files changed, 593 insertions(+), 19 deletions(-)
 create mode 100644 gcc/config/bpf/atomic.md
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-cmpxchg-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-cmpxchg-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-fetch-op-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-fetch-op-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-fetch-op-3.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-op-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-op-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-op-3.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-xchg-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-xchg-2.c

diff --git a/gcc/config/bpf/atomic.md b/gcc/config/bpf/atomic.md
new file mode 100644
index 000..caf8cc15cd4
--- /dev/null
+++ b/gcc/config/bpf/atomic.md
@@ -0,0 +1,185 @@
+;; Machine description for eBPF.
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; .
+
+
+(define_mode_iterator AMO [SI DI])
+
+;;; Plain atomic modify operations.
+
+;; Non-fetching atomic add predates all other BPF atomic insns.
+;; Use xadd{w,dw} for compatibility with older GAS without support
+;; for v3 atomics.  Newer GAS supports "aadd[32]" in line with the
+;; other atom

Re: [PATCH 1/2] bpf: don't print () in bpf_print_operand_address

2023-07-25 Thread David Faust via Gcc-patches



On 7/25/23 15:14, Jose E. Marchesi wrote:
> 
> Hi David.
> 
>> Unfortunately, the pseudo-C dialect syntax used for some of the v3
>> atomic instructions clashes with unconditionally printing the
>> surrounding parentheses in bpf_print_operand_address.
>>
>> Instead, place the parentheses in the output templates where needed.
>>
>> Tested in bpf-unknown-none.
>> OK?
>>
>> gcc/
>>
>>  * config/bpf/bpf.cc (bpf_print_operand_address): Don't print
>>  enclosing parentheses for pseudo-C dialect.
>>  * config/bpf/bpf.md (zero_exdendhidi2): Add parentheses around
>>  operands of pseudo-C dialect output templates where needed.
>>  (zero_extendqidi2): Likewise.
>>  (zero_extendsidi2): Likewise.
>>  (*mov): Likewise.
>> ---
>>  gcc/config/bpf/bpf.cc |  8 
>>  gcc/config/bpf/bpf.md | 12 ++--
>>  2 files changed, 10 insertions(+), 10 deletions(-)
>>
>> diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
>> index 55b6927a62f..2c077ea834e 100644
>> --- a/gcc/config/bpf/bpf.cc
>> +++ b/gcc/config/bpf/bpf.cc
>> @@ -933,9 +933,9 @@ bpf_print_operand_address (FILE *file, rtx addr)
>>switch (GET_CODE (addr))
>>  {
>>  case REG:
>> -  fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
>> +  fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "");
> 
> We can save the call to fprintf there with a conditional.

Good point, thanks.
I will update these before pushing.

> 
>>bpf_print_register (file, addr, 0);
>> -  fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0)");
>> +  fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0");
>>break;
>>  case PLUS:
>>{
>> @@ -944,11 +944,11 @@ bpf_print_operand_address (FILE *file, rtx addr)
>>  
>>  if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
>>{
>> -fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
>> +fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "");
> 
> Likewise.
> 
>>  bpf_print_register (file, op0, 0);
>>  fprintf (file, "+");
>>  output_addr_const (file, op1);
>> -fprintf (file, asm_dialect == ASM_NORMAL ? "]" : ")");
>> +fprintf (file, asm_dialect == ASM_NORMAL ? "]" : "");
>>}
>>  else
>>fatal_insn ("invalid address in operand", addr);
>> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
>> index 64342ea1de2..579a8213b09 100644
>> --- a/gcc/config/bpf/bpf.md
>> +++ b/gcc/config/bpf/bpf.md
>> @@ -260,7 +260,7 @@ (define_insn "zero_extendhidi2"
>>"@
>> {and\t%0,0x|%0 &= 0x}
>> {mov\t%0,%1\;and\t%0,0x|%0 = %1;%0 &= 0x}
>> -   {ldxh\t%0,%1|%0 = *(u16 *) %1}"
>> +   {ldxh\t%0,%1|%0 = *(u16 *) (%1)}"
>>[(set_attr "type" "alu,alu,ldx")])
>>  
>>  (define_insn "zero_extendqidi2"
>> @@ -270,7 +270,7 @@ (define_insn "zero_extendqidi2"
>>"@
>> {and\t%0,0xff|%0 &= 0xff}
>> {mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}
>> -   {ldxh\t%0,%1|%0 = *(u8 *) %1}"
>> +   {ldxh\t%0,%1|%0 = *(u8 *) (%1)}"
>>[(set_attr "type" "alu,alu,ldx")])
>>  
>>  (define_insn "zero_extendsidi2"
>> @@ -280,7 +280,7 @@ (define_insn "zero_extendsidi2"
>>""
>>"@
>> * return bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : 
>> \"{mov\t%0,%1\;and\t%0,0x|%0 = %1;%0 &= 0x}\";
>> -   {ldxw\t%0,%1|%0 = *(u32 *) %1}"
>> +   {ldxw\t%0,%1|%0 = *(u32 *) (%1)}"
>>[(set_attr "type" "alu,ldx")])
>>  
>>  ;;; Sign-extension
>> @@ -319,11 +319,11 @@ (define_insn "*mov"
>>  (match_operand:MM 1 "mov_src_operand"  " q,rI,B,r,I"))]
>>""
>>"@
>> -   {ldx\t%0,%1|%0 = *( *) %1}
>> +   {ldx\t%0,%1|%0 = *( *) (%1)}
>> {mov\t%0,%1|%0 = %1}
>> {lddw\t%0,%1|%0 = %1 ll}
>> -   {stx\t%0,%1|*( *) %0 = %1}
>> -   {st\t%0,%1|*( *) %0 = %1}"
>> +   {stx\t%0,%1|*( *) (%0) = %1}
>> +   {st\t%0,%1|*( *) (%0) = %1}"
>>  [(set_attr "type" "ldx,alu,alu,stx,st")])
>>  
>>   Shifts
> 
> Otherwise, LGTM.
> OK.
> 
> Thanks!


Re: [PATCH 2/2] bpf: add v3 atomic instructions

2023-07-25 Thread David Faust via Gcc-patches



On 7/25/23 15:18, Jose E. Marchesi wrote:
> 
> Hi David.
> 
>> +<<< HEAD
> 
> There is a merge problem there.

Ugh, I swear I've fixed this twice now. Yet it keeps cropping up.
Sorry. v2 shortly.

> 
>>  @opindex mbswap
>>  @item -mbswap
>>  Enable byte swap instructions.  Enabled for CPU v4 and above.
>> @@ -24715,6 +24716,12 @@ Enable byte swap instructions.  Enabled for CPU v4 
>> and above.
>>  @item -msdiv
>>  Enable signed division and modulus instructions.  Enabled for CPU v4
>>  and above.
>> +===
>> +@opindex mv3-atomics
>> +@item -mv3-atomics
>> +Enable instructions for general atomic operations introduced in CPU v3.
>> +Enabled for CPU v3 and above.
>> +>>> 6de76bd11b6 (bpf: add v3 atomic instructions)


[PATCH 2/2] bpf: add v3 atomic instructions

2023-07-25 Thread David Faust via Gcc-patches
This patch adds support for the general atomic operations introduced in
eBPF v3. In addition to the existing atomic add instruction, this adds:
 - Atomic and, or, xor
 - Fetching versions of these operations (including add)
 - Atomic exchange
 - Atomic compare-and-exchange

To control emission of these instructions, a new target option
-m[no-]v3-atomics is added. This option is enabled by -mcpu=v3
and above.

Support for these instructions was recently added in binutils.

Tested in bpf-unknown-none.
OK?

gcc/

* config/bpf/bpf.opt (mv3-atomics): New option.
* config/bpf/bpf.cc (bpf_option_override): Handle it here.
* config/bpf/bpf.h (enum_reg_class): Add R0 class.
(REG_CLASS_NAMES): Likewise.
(REG_CLASS_CONTENTS): Likewise.
(REGNO_REG_CLASS): Handle R0.
* config/bpf/bpf.md (UNSPEC_XADD): Rename to UNSPEC_AADD.
(UNSPEC_AAND): New unspec.
(UNSPEC_AOR): Likewise.
(UNSPEC_AXOR): Likewise.
(UNSPEC_AFADD): Likewise.
(UNSPEC_AFAND): Likewise.
(UNSPEC_AFOR): Likewise.
(UNSPEC_AFXOR): Likewise.
(UNSPEC_AXCHG): Likewise.
(UNSPEC_ACMPX): Likewise.
(atomic_add): Use UNSPEC_AADD and atomic type attribute.
Move to...
* config/bpf/atomic.md: ...Here. New file.
* config/bpf/constraints.md (t): New constraint for R0.
* doc/invoke.texi (eBPF Options): Document -mv3-atomics.

gcc/testsuite/

* gcc.target/bpf/atomic-cmpxchg-1.c: New test.
* gcc.target/bpf/atomic-cmpxchg-2.c: New test.
* gcc.target/bpf/atomic-fetch-op-1.c: New test.
* gcc.target/bpf/atomic-fetch-op-2.c: New test.
* gcc.target/bpf/atomic-fetch-op-3.c: New test.
* gcc.target/bpf/atomic-op-1.c: New test.
* gcc.target/bpf/atomic-op-2.c: New test.
* gcc.target/bpf/atomic-op-3.c: New test.
* gcc.target/bpf/atomic-xchg-1.c: New test.
* gcc.target/bpf/atomic-xchg-2.c: New test.
---
 gcc/config/bpf/atomic.md  | 185 ++
 gcc/config/bpf/bpf.cc |   3 +
 gcc/config/bpf/bpf.h  |   6 +-
 gcc/config/bpf/bpf.md |  29 ++-
 gcc/config/bpf/bpf.opt|   4 +
 gcc/config/bpf/constraints.md |   3 +
 gcc/doc/invoke.texi   |  10 +-
 .../gcc.target/bpf/atomic-cmpxchg-1.c |  19 ++
 .../gcc.target/bpf/atomic-cmpxchg-2.c |  19 ++
 .../gcc.target/bpf/atomic-fetch-op-1.c|  50 +
 .../gcc.target/bpf/atomic-fetch-op-2.c|  50 +
 .../gcc.target/bpf/atomic-fetch-op-3.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-op-1.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-op-2.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-op-3.c|  49 +
 gcc/testsuite/gcc.target/bpf/atomic-xchg-1.c  |  20 ++
 gcc/testsuite/gcc.target/bpf/atomic-xchg-2.c  |  20 ++
 17 files changed, 595 insertions(+), 19 deletions(-)
 create mode 100644 gcc/config/bpf/atomic.md
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-cmpxchg-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-cmpxchg-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-fetch-op-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-fetch-op-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-fetch-op-3.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-op-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-op-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-op-3.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-xchg-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/atomic-xchg-2.c

diff --git a/gcc/config/bpf/atomic.md b/gcc/config/bpf/atomic.md
new file mode 100644
index 000..caf8cc15cd4
--- /dev/null
+++ b/gcc/config/bpf/atomic.md
@@ -0,0 +1,185 @@
+;; Machine description for eBPF.
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING3.  If not see
+;; .
+
+
+(define_mode_iterator AMO [SI DI])
+
+;;; Plain atomic modify operations.
+
+;; Non-fetching atomic add predates all other BPF atomic insns.
+;; Use xadd{w,dw} for compatibility with older GAS without support
+;; for v3 atomics.  Newer GAS supports "aadd[32]" in line with the
+;; other atomic operations.
+(d

[PATCH 1/2] bpf: don't print () in bpf_print_operand_address

2023-07-25 Thread David Faust via Gcc-patches
Unfortunately, the pseudo-C dialect syntax used for some of the v3
atomic instructions clashes with unconditionally printing the
surrounding parentheses in bpf_print_operand_address.

Instead, place the parentheses in the output templates where needed.

Tested in bpf-unknown-none.
OK?

gcc/

* config/bpf/bpf.cc (bpf_print_operand_address): Don't print
enclosing parentheses for pseudo-C dialect.
* config/bpf/bpf.md (zero_exdendhidi2): Add parentheses around
operands of pseudo-C dialect output templates where needed.
(zero_extendqidi2): Likewise.
(zero_extendsidi2): Likewise.
(*mov): Likewise.
---
 gcc/config/bpf/bpf.cc |  8 
 gcc/config/bpf/bpf.md | 12 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 55b6927a62f..2c077ea834e 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -933,9 +933,9 @@ bpf_print_operand_address (FILE *file, rtx addr)
   switch (GET_CODE (addr))
 {
 case REG:
-  fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+  fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "");
   bpf_print_register (file, addr, 0);
-  fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0)");
+  fprintf (file, asm_dialect == ASM_NORMAL ? "+0]" : "+0");
   break;
 case PLUS:
   {
@@ -944,11 +944,11 @@ bpf_print_operand_address (FILE *file, rtx addr)
 
if (GET_CODE (op0) == REG && GET_CODE (op1) == CONST_INT)
  {
-   fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "(");
+   fprintf (file, asm_dialect == ASM_NORMAL ? "[" : "");
bpf_print_register (file, op0, 0);
fprintf (file, "+");
output_addr_const (file, op1);
-   fprintf (file, asm_dialect == ASM_NORMAL ? "]" : ")");
+   fprintf (file, asm_dialect == ASM_NORMAL ? "]" : "");
  }
else
  fatal_insn ("invalid address in operand", addr);
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 64342ea1de2..579a8213b09 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -260,7 +260,7 @@ (define_insn "zero_extendhidi2"
   "@
{and\t%0,0x|%0 &= 0x}
{mov\t%0,%1\;and\t%0,0x|%0 = %1;%0 &= 0x}
-   {ldxh\t%0,%1|%0 = *(u16 *) %1}"
+   {ldxh\t%0,%1|%0 = *(u16 *) (%1)}"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendqidi2"
@@ -270,7 +270,7 @@ (define_insn "zero_extendqidi2"
   "@
{and\t%0,0xff|%0 &= 0xff}
{mov\t%0,%1\;and\t%0,0xff|%0 = %1;%0 &= 0xff}
-   {ldxh\t%0,%1|%0 = *(u8 *) %1}"
+   {ldxh\t%0,%1|%0 = *(u8 *) (%1)}"
   [(set_attr "type" "alu,alu,ldx")])
 
 (define_insn "zero_extendsidi2"
@@ -280,7 +280,7 @@ (define_insn "zero_extendsidi2"
   ""
   "@
* return bpf_has_alu32 ? \"{mov32\t%0,%1|%0 = %1}\" : 
\"{mov\t%0,%1\;and\t%0,0x|%0 = %1;%0 &= 0x}\";
-   {ldxw\t%0,%1|%0 = *(u32 *) %1}"
+   {ldxw\t%0,%1|%0 = *(u32 *) (%1)}"
   [(set_attr "type" "alu,ldx")])
 
 ;;; Sign-extension
@@ -319,11 +319,11 @@ (define_insn "*mov"
 (match_operand:MM 1 "mov_src_operand"  " q,rI,B,r,I"))]
   ""
   "@
-   {ldx\t%0,%1|%0 = *( *) %1}
+   {ldx\t%0,%1|%0 = *( *) (%1)}
{mov\t%0,%1|%0 = %1}
{lddw\t%0,%1|%0 = %1 ll}
-   {stx\t%0,%1|*( *) %0 = %1}
-   {st\t%0,%1|*( *) %0 = %1}"
+   {stx\t%0,%1|*( *) (%0) = %1}
+   {st\t%0,%1|*( *) (%0) = %1}"
 [(set_attr "type" "ldx,alu,alu,stx,st")])
 
  Shifts
-- 
2.40.1



[COMMITTED] bpf: add pseudo-c asm dialect for "nop"

2023-07-24 Thread David Faust via Gcc-patches
The define_insn "nop" was missing a template for the pseudo-c dialect,
so the normal syntax was unconditionally emitted.

Tested on bpf-unknown-none, committed as obvious.

gcc/

* config/bpf/bpf.md (nop): Add pseudo-c asm dialect template.
---
 gcc/config/bpf/bpf.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 3e2d760fbe4..64342ea1de2 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -103,7 +103,7 @@ (define_mode_attr msuffix [(SI "32") (DI "")])
 (define_insn "nop"
   [(const_int 0)]
   ""
-  "ja\t0"
+  "{ja\t0|goto 0}"
   [(set_attr "type" "alu")])
 
  Arithmetic/Logical
-- 
2.40.1



Re: [PATCH 0/9] Add btf_decl_tag C attribute

2023-07-24 Thread David Faust via Gcc-patches
Gentle ping.

https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624156.html

On 7/11/23 14:57, David Faust via Gcc-patches wrote:
> Hello,
> 
> This series adds support for a new attribute, "btf_decl_tag" in GCC.
> The same attribute is already supported in clang, and is used by various
> components of the BPF ecosystem.
> 
> The purpose of the attribute is to allow to associate (to "tag")
> declarations with arbitrary string annotations, which are emitted into
> debugging information (DWARF and/or BTF) to facilitate post-compilation
> analysis (the motivating use case being the Linux kernel BPF verifier).
> Multiple tags are allowed on the same declaration.
> 
> These strings are not interpreted by the compiler, and the attribute
> itself has no effect on generated code, other than to produce additional
> DWARF DIEs and/or BTF records conveying the annotations.
> 
> This entails:
> 
> - A new C-language-level attribute which allows to associate (to "tag")
>   particular declarations with arbitrary strings.
> 
> - The conveyance of that information in DWARF in the form of a new DIE,
>   DW_TAG_GNU_annotation, with tag number (0x6000) and format matching
>   that of the DW_TAG_LLVM_annotation extension supported in LLVM for
>   the same purpose. These DIEs are already supported by BPF tooling,
>   such as pahole.
> 
> - The conveyance of that information in BTF debug info in the form of
>   BTF_KIND_DECL_TAG records. These records are already supported by
>   LLVM and other tools in the eBPF ecosystem, such as the Linux kernel
>   eBPF verifier.
> 
> 
> Background
> ==
> 
> The purpose of these tags is to convey additional semantic information
> to post-compilation consumers, in particular the Linux kernel eBPF
> verifier. The verifier can make use of that information while analyzing
> a BPF program to aid in determining whether to allow or reject the
> program to be run. More background on these tags can be found in the
> early support for them in the kernel here [1] and [2].
> 
> The "btf_decl_tag" attribute is half the story; the other half is a
> sibling attribute "btf_type_tag" which serves the same purpose but
> applies to types. Support for btf_type_tag will come in a separate
> patch series, since it is impaced by GCC bug 110439 which needs to be
> addressed first.
> 
> I submitted an initial version of this work (including btf_type_tag)
> last spring [3], however at the time there were some open questions
> about the behavior of the btf_type_tag attribute and issues with its
> implementation. Since then we have clarified these details and agreed
> to solutions with the BPF community and LLVM BPF folks.
> 
> The main motivation for emitting the tags in DWARF is that the Linux
> kernel generates its BTF information via pahole, using DWARF as a source:
> 
> ++  BTF  BTF   +--+
> | pahole |---> vmlinux.btf --->| verifier |
> ++ +--+
> ^^
> ||
>   DWARF |BTF |
> ||
>   vmlinux  +-+
>   module1.ko   | BPF program |
>   module2.ko   +-+
> ...
> 
> This is because:
> 
> a)  pahole adds additional kernel-specific information into the
> produced BTF based on additional analysis of kernel objects.
> 
> b)  Unlike GCC, LLVM will only generate BTF for BPF programs.
> 
> b)  GCC can generate BTF for whatever target with -gbtf, but there is no
> support for linking/deduplicating BTF in the linker.
> 
> In the scenario above, the verifier needs access to the pointer tags of
> both the kernel types/declarations (conveyed in the DWARF and translated
> to BTF by pahole) and those of the BPF program (available directly in BTF).
> 
> 
> DWARF Representation
> 
> 
> As noted above, btf_decl_tag is represented in DWARF via a new DIE
> DW_TAG_GNU_annotation, with identical format to the LLVM DWARF
> extension DW_TAG_LLVM_annotation serving the same purpose. The DIE has
> the following format:
> 
>   DW_TAG_GNU_annotation (0x6000)
> DW_AT_name: "btf_decl_tag"
> DW_AT_const_value: 
> 
> These DIEs are placed in the DWARF tree as children of the DIE for the
> appropriate declaration, and one such DIE is created for each occurrence
> of the btf_decl_tag attribute on a declaration.
> 
> For example:
> 
>   const int 

Re: [PATCH] bpf: fixed template for neg (added second operand)

2023-07-21 Thread David Faust via Gcc-patches
Hi Cupertino,

On 7/21/23 09:43, Cupertino Miranda wrote:
> gcc/ChangeLog:
> 
>   * config/bpf/bpf.md: fixed template for neg instruction.
> ---
>  gcc/config/bpf/bpf.md | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
> index 329f62f55c33..bb414d8a4428 100644
> --- a/gcc/config/bpf/bpf.md
> +++ b/gcc/config/bpf/bpf.md
> @@ -142,7 +142,7 @@
>[(set (match_operand:AM 0 "register_operand" "=r")
>  (neg:AM (match_operand:AM 1 "register_operand" " 0")))]
>""
> -  "neg\t%0"
> +  "neg\t%0,%1"
>[(set_attr "type" "")])

I think you will need to update the constraint for the second
operand as well; it could be any register, or a 32-bit immediate.

>  
>  ;;; Multiplication


Re: [PATCH 0/9] Add btf_decl_tag C attribute

2023-07-12 Thread David Faust via Gcc-patches



On 7/12/23 06:49, Jose E. Marchesi wrote:
> 
>> On Wed, Jul 12, 2023 at 2:44 PM Jose E. Marchesi
>>  wrote:
>>>
>>>
>>> [Added Eduard Zingerman in CC, who is implementing this same feature in
>>>  clang/llvm and also the consumer component in the kernel (pahole).]
>>>
>>> Hi Richard.
>>>
>>>> On Tue, Jul 11, 2023 at 11:58 PM David Faust via Gcc-patches
>>>>  wrote:
>>>>>
>>>>> Hello,
>>>>>
>>>>> This series adds support for a new attribute, "btf_decl_tag" in GCC.
>>>>> The same attribute is already supported in clang, and is used by various
>>>>> components of the BPF ecosystem.
>>>>>
>>>>> The purpose of the attribute is to allow to associate (to "tag")
>>>>> declarations with arbitrary string annotations, which are emitted into
>>>>> debugging information (DWARF and/or BTF) to facilitate post-compilation
>>>>> analysis (the motivating use case being the Linux kernel BPF verifier).
>>>>> Multiple tags are allowed on the same declaration.
>>>>>
>>>>> These strings are not interpreted by the compiler, and the attribute
>>>>> itself has no effect on generated code, other than to produce additional
>>>>> DWARF DIEs and/or BTF records conveying the annotations.
>>>>>
>>>>> This entails:
>>>>>
>>>>> - A new C-language-level attribute which allows to associate (to "tag")
>>>>>   particular declarations with arbitrary strings.
>>>>>
>>>>> - The conveyance of that information in DWARF in the form of a new DIE,
>>>>>   DW_TAG_GNU_annotation, with tag number (0x6000) and format matching
>>>>>   that of the DW_TAG_LLVM_annotation extension supported in LLVM for
>>>>>   the same purpose. These DIEs are already supported by BPF tooling,
>>>>>   such as pahole.
>>>>>
>>>>> - The conveyance of that information in BTF debug info in the form of
>>>>>   BTF_KIND_DECL_TAG records. These records are already supported by
>>>>>   LLVM and other tools in the eBPF ecosystem, such as the Linux kernel
>>>>>   eBPF verifier.
>>>>>
>>>>>
>>>>> Background
>>>>> ==
>>>>>
>>>>> The purpose of these tags is to convey additional semantic information
>>>>> to post-compilation consumers, in particular the Linux kernel eBPF
>>>>> verifier. The verifier can make use of that information while analyzing
>>>>> a BPF program to aid in determining whether to allow or reject the
>>>>> program to be run. More background on these tags can be found in the
>>>>> early support for them in the kernel here [1] and [2].
>>>>>
>>>>> The "btf_decl_tag" attribute is half the story; the other half is a
>>>>> sibling attribute "btf_type_tag" which serves the same purpose but
>>>>> applies to types. Support for btf_type_tag will come in a separate
>>>>> patch series, since it is impaced by GCC bug 110439 which needs to be
>>>>> addressed first.
>>>>>
>>>>> I submitted an initial version of this work (including btf_type_tag)
>>>>> last spring [3], however at the time there were some open questions
>>>>> about the behavior of the btf_type_tag attribute and issues with its
>>>>> implementation. Since then we have clarified these details and agreed
>>>>> to solutions with the BPF community and LLVM BPF folks.
>>>>>
>>>>> The main motivation for emitting the tags in DWARF is that the Linux
>>>>> kernel generates its BTF information via pahole, using DWARF as a source:
>>>>>
>>>>> ++  BTF  BTF   +--+
>>>>> | pahole |---> vmlinux.btf --->| verifier |
>>>>> ++ +--+
>>>>> ^^
>>>>> ||
>>>>>   DWARF |BTF |
>>>>> ||
>>>>>   vmlinux  +-+
>>>>>   module1.ko  

[PATCH 7/9] btf: create and output BTF_KIND_DECL_TAG types

2023-07-11 Thread David Faust via Gcc-patches
This patch updates btfout.cc to be aware of BTF_KIND_DECL_TAG types and
output them appropriately.

gcc/

* btfout.cc (funcs_map): New hash map.
(btf_emit_preprocess): ... Initialize it here...
(btf_collect_datasec): ... Populate it here...
(btf_finalize): ... And free it here.
(get_btf_kind): Handle BTF_KIND_DECL_TAG.
(calc_num_vbytes): Likewise.
(btf_asm_type): Likewise.
(output_asm_btf_vlen_bytes): Likewise.
(btf_asm_type_ref): Update comment.
---
 gcc/btfout.cc | 79 +--
 1 file changed, 76 insertions(+), 3 deletions(-)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index e6acf4e51a5..087d0b40e0a 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -104,6 +104,9 @@ static vec voids;
created. This vector holds them.  */
 static GTY (()) vec *funcs;
 
+/* Maps FUNC_PROTO types to the IDs of the corresponding FUNC types.  */
+static GTY (()) hash_map  *funcs_map;
+
 /* The number of BTF variables added to the TU CTF container.  */
 static unsigned int num_vars_added = 0;
 
@@ -153,6 +156,7 @@ get_btf_kind (uint32_t ctf_kind)
 case CTF_K_VOLATILE: return BTF_KIND_VOLATILE;
 case CTF_K_CONST:return BTF_KIND_CONST;
 case CTF_K_RESTRICT: return BTF_KIND_RESTRICT;
+case CTFC_INT_K_DECL_TAG: return BTF_KIND_DECL_TAG;
 default:;
 }
   return BTF_KIND_UNKN;
@@ -316,6 +320,10 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
   vlen_bytes += vlen * sizeof (struct btf_var_secinfo);
   break;
 
+case BTF_KIND_DECL_TAG:
+  vlen_bytes += sizeof (struct btf_decl_tag);
+  break;
+
 default:
   break;
 }
@@ -425,13 +433,15 @@ btf_collect_datasec (ctf_container_ref ctfc)
   func_dtd->dtd_data = dtd->dtd_data;
   func_dtd->dtd_data.ctti_type = dtd->dtd_type;
   func_dtd->linkage = dtd->linkage;
-  func_dtd->dtd_type = num_types_added + num_types_created;
+  /* +1 for the sentinel type not in the types map.  */
+  func_dtd->dtd_type = num_types_added + num_types_created + 1;
 
   /* Only the BTF_KIND_FUNC type actually references the name. The
 BTF_KIND_FUNC_PROTO is always anonymous.  */
   dtd->dtd_data.ctti_name = 0;
 
   vec_safe_push (funcs, func_dtd);
+  funcs_map->put (dtd, func_dtd->dtd_type);
   num_types_created++;
 
   /* Mark any 'extern' funcs and add DATASEC entries for them.  */
@@ -449,7 +459,7 @@ btf_collect_datasec (ctf_container_ref ctfc)
  struct btf_var_secinfo info;
 
  /* +1 for the sentinel type not in the types map.  */
- info.type = func_dtd->dtd_type + 1;
+ info.type = func_dtd->dtd_type;
 
  /* Both zero at compile time.  */
  info.size = 0;
@@ -653,6 +663,7 @@ btf_emit_preprocess (ctf_container_ref ctfc)
 }
 
   btf_var_ids = hash_map::create_ggc (100);
+  funcs_map = hash_map::create_ggc (100);
 
   if (num_ctf_vars)
 {
@@ -709,7 +720,8 @@ btf_asm_type_ref (const char *prefix, ctf_container_ref 
ctfc, ctf_id_t ref_id)
   else if (ref_id >= num_types_added + 1
   && ref_id < num_types_added + num_vars_added + 1)
 {
-  /* Ref to a variable.  Should only appear in DATASEC entries.  */
+  /* Ref to a variable.
+Should only appear in DATASEC entries or DECL_TAGs.  */
   ctf_id_t var_id = btf_relative_var_id (ref_id);
   ctf_dvdef_ref dvd = ctfc->ctfc_vars_list[var_id];
   dw2_asm_output_data (4, ref_id, "%s: (BTF_KIND_VAR '%s')",
@@ -831,6 +843,59 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
 and should write 0.  */
   dw2_asm_output_data (4, 0, "(unused)");
   return;
+case BTF_KIND_DECL_TAG:
+  {
+   /* A decl tag might refer to (be the child DIE of) a variable.  Try to
+  lookup the parent DIE's CTF variable, and if it exists point to the
+  corresponding BTF variable.  This is an odd construction - we have a
+  'type' which refers to a variable, rather than the reverse.  */
+   dw_die_ref parent = get_die_parent (dtd->dtd_key);
+   ctf_dvdef_ref ref_dvd = ctf_dvd_lookup (ctfc, parent);
+   ctf_dtdef_ref ref_dtd = ctf_dtd_lookup (ctfc, parent);
+   if (ref_dvd)
+ {
+   /* The decl tag is on a variable.  */
+   unsigned int *var_id = btf_var_ids->get (ref_dvd);
+   gcc_assert (var_id);
+   btf_asm_type_ref ("btt_type", ctfc,
+ btf_absolute_var_id (*var_id));
+   return;
+ }
+   else if (ref_dtd)
+ {
+   /* Decl tags on functions refer to the FUNC_PROTO record as a
+  result of how they are created.  But we want them in the output
+  to refer to the synthesized FUNC record instead.  */
+   unsigned int *func_id = funcs_map->get (ref_dtd);
+   gcc_assert (func_id);
+   btf_asm_type_ref ("btt_type", ctfc, *func_id);
+   return;
+ }
+ 

[PATCH 1/9] c-family: add btf_decl_tag attribute

2023-07-11 Thread David Faust via Gcc-patches
Add the "btf_decl_tag" attribute to the attribute table, along with
a simple handler for it.

gcc/c-family/

* c-attribs.cc (c_common_attribute_table): Add btf_decl_tag.
(handle_btf_decl_tag_attribute): Handle new attribute.
---
 gcc/c-family/c-attribs.cc | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index e2792ca6898..0a3de3ea307 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -178,6 +178,8 @@ static tree handle_signed_bool_precision_attribute (tree *, 
tree, tree, int,
 static tree handle_retain_attribute (tree *, tree, tree, int, bool *);
 static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *);
 
+static tree handle_btf_decl_tag_attribute (tree *, tree, tree, int, bool *);
+
 /* Helper to define attribute exclusions.  */
 #define ATTR_EXCL(name, function, type, variable)  \
   { name, function, type, variable }
@@ -569,6 +571,9 @@ const struct attribute_spec c_common_attribute_table[] =
 handle_fd_arg_attribute, NULL},
   { "fd_arg_write",   1, 1, false, true, true, false,
 handle_fd_arg_attribute, NULL}, 
+  { "btf_decl_tag",  1, 1, true, false, false, false,
+ handle_btf_decl_tag_attribute, NULL },
+
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
 };
 
@@ -5988,6 +5993,24 @@ handle_tainted_args_attribute (tree *node, tree name, 
tree, int,
   return NULL_TREE;
 }
 
+/* Handle a "btf_decl_tag" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_btf_decl_tag_attribute (tree *, tree name, tree args, int,
+  bool *no_add_attrs)
+{
+  if (!args)
+*no_add_attrs = true;
+  else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+{
+  error ("%qE attribute requires a string", name);
+  *no_add_attrs = true;
+}
+
+  return NULL_TREE;
+}
+
 /* Attempt to partially validate a single attribute ATTR as if
it were to be applied to an entity OPER.  */
 
-- 
2.40.1



[PATCH 8/9] testsuite: add tests for BTF decl tags

2023-07-11 Thread David Faust via Gcc-patches
This patch adds tests for the btf_decl_tag attribute, in both DWARF
and BTF.

gcc/testsuite/

* gcc.dg/debug/btf/btf-decltag-func.c: New test.
* gcc.dg/debug/btf/btf-decltag-sou.c: New test.
* gcc.dg/debug/btf/btf-decltag-var.c: New test.
* gcc.dg/debug/dwarf2/annotation-decl-1.c: New test.
* gcc.dg/debug/dwarf2/annotation-decl-2.c: New test.
* gcc.dg/debug/dwarf2/annotation-decl-3.c: New test.
---
 .../gcc.dg/debug/btf/btf-decltag-func.c   | 21 
 .../gcc.dg/debug/btf/btf-decltag-sou.c| 33 +++
 .../gcc.dg/debug/btf/btf-decltag-var.c| 19 +++
 .../gcc.dg/debug/dwarf2/annotation-decl-1.c   |  9 +
 .../gcc.dg/debug/dwarf2/annotation-decl-2.c   | 18 ++
 .../gcc.dg/debug/dwarf2/annotation-decl-3.c   | 17 ++
 6 files changed, 117 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-var.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-decl-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-decl-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-decl-3.c

diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
new file mode 100644
index 000..12a5eff9ac7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
@@ -0,0 +1,21 @@
+/* { dg-do compile }  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+#define __tag1 __attribute__((btf_decl_tag("decl-tag-1")))
+#define __tag2 __attribute__((btf_decl_tag("decl-tag-2")))
+#define __tag3 __attribute__((btf_decl_tag("decl-tag-3")))
+
+extern int bar (int __tag1, int __tag2) __tag3;
+
+int __tag1 __tag2 foo (int arg1, int *arg2 __tag2)
+  {
+return bar (arg1 + 1, *arg2 + 2);
+  }
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 4 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+
+/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 
'decl-tag-1'\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\\(BTF_KIND_FUNC" 1 } 
} */
+/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 
'decl-tag-2'\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\\(BTF_KIND_FUNC" 2 } 
} */
+/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 
'decl-tag-3'\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\\(BTF_KIND_FUNC" 1 } 
} */
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
new file mode 100644
index 000..13c9f075b1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
@@ -0,0 +1,33 @@
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 13 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*decltag_compidx" 
2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+
+#define __tag1 __attribute__((btf_decl_tag("decl-tag-1")))
+#define __tag2 __attribute__((btf_decl_tag("decl-tag-2")))
+#define __tag3 __attribute__((btf_decl_tag("decl-tag-3")))
+
+struct t {
+  int a;
+  long b __tag3;
+  char c __tag2 __tag3;
+};
+
+struct t my_t __tag1 __tag2;
+
+union u {
+  char one __tag1 __tag2;
+  short two;
+  int three __tag1;
+  long four __tag1 __tag2 __tag3;
+  long long five __tag2;
+};
+
+union u my_u __tag3;
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-var.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-var.c
new file mode 100644
index 000..563e8838f1a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-var.c
@@ -0,0 +1,19 @@
+/* { dg-do compile }  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+unsigned long u __attribute__((btf_decl_tag ("__u")));
+
+const int * c __attribute__((btf_decl_tag ("__c"), btf_decl_tag 
("devicemem")));
+
+struct st
+{
+  int a;
+  char c;
+};
+
+struct st my_st __attribute__((btf_decl_tag ("__my_st")));
+
+/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 
'__u'\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\\(BTF_KIND_VAR 'u'" 1 } } */
+/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG 
'__c'\[\\r\\n\]+\[^\\r\\n\]*\[\\r\\n\]+\[^\\r\\n\]*\\(BTF_KIND_VAR 'c'" 1 } } */
+/* { dg-final { scan-assembler-times " BTF_KIND_DECL_TAG

[PATCH 6/9] dwarf2ctf: convert annotation DIEs to CTF types

2023-07-11 Thread David Faust via Gcc-patches
This patch makes the DWARF-to-CTF conversion process aware of the new
DW_TAG_GNU_annotation DIEs. The DIEs are converted to CTF_K_DECL_TAG
types and added to the compilation unit CTF container to be translated
to BTF and output.

gcc/

* dwarf2ctf.cc (handle_btf_tags): New function.
(gen_ctf_sou_type): Don't try to create member types for children which
are not DW_TAG_member. Call handle_btf_tags if appropriate.
(gen_ctf_function_type): Call handle_btf_tags if appropriate.
(gen_ctf_variable): Likewise.
(gen_ctf_type): Likewise.
---
 gcc/dwarf2ctf.cc | 71 +++-
 1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
index 549b0cb2dc1..b051aef45a8 100644
--- a/gcc/dwarf2ctf.cc
+++ b/gcc/dwarf2ctf.cc
@@ -32,6 +32,9 @@ along with GCC; see the file COPYING3.  If not see
 static ctf_id_t
 gen_ctf_type (ctf_container_ref, dw_die_ref);
 
+static void
+handle_btf_tags (ctf_container_ref, dw_die_ref, ctf_id_t, int);
+
 /* All the DIE structures we handle come from the DWARF information
generated by GCC.  However, there are three situations where we need
to create our own created DIE structures because GCC doesn't
@@ -547,6 +550,7 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
   /* Now process the struct members.  */
   {
 dw_die_ref c;
+int idx = 0;
 
 c = dw_get_die_child (sou);
 if (c)
@@ -559,6 +563,9 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
 
  c = dw_get_die_sib (c);
 
+ if (dw_get_die_tag (c) != DW_TAG_member)
+   continue;
+
  field_name = get_AT_string (c, DW_AT_name);
  field_type = ctf_get_AT_type (c);
  field_location = ctf_get_AT_data_member_location (c);
@@ -626,6 +633,12 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
 field_name,
 field_type_id,
 field_location);
+
+ /* Handle BTF tags on the member.  */
+ if (btf_debuginfo_p ())
+   handle_btf_tags (ctfc, c, sou_type_id, idx);
+
+ idx++;
}
   while (c != dw_get_die_child (sou));
   }
@@ -718,6 +731,9 @@ gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref 
function,
  arg_type = gen_ctf_type (ctfc, ctf_get_AT_type (c));
  /* Add the argument to the existing CTF function type.  */
  ctf_add_function_arg (ctfc, function, arg_name, arg_type);
+
+ if (btf_debuginfo_p ())
+   handle_btf_tags (ctfc, c, function_type_id, i - 1);
}
  else
/* This is a local variable.  Ignore.  */
@@ -833,6 +849,11 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
   /* Skip updating the number of global objects at this time.  This is updated
  later after pre-processing as some CTF variable records although
  generated now, will not be emitted later.  [PR105089].  */
+
+  /* Handle any BTF tags on the variable.  */
+  if (btf_debuginfo_p ())
+handle_btf_tags (ctfc, die, CTF_NULL_TYPEID, -1);
+
 }
 
 /* Add a CTF function record for the given input DWARF DIE.  */
@@ -850,8 +871,13 @@ gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die)
  counter.  Note that DWARF encodes function types in both
  DW_TAG_subroutine_type and DW_TAG_subprogram in exactly the same
  way.  */
-  (void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
+  function_type_id
+   = gen_ctf_function_type (ctfc, die, true /* from_global_func 
*/);
   ctfc->ctfc_num_global_funcs += 1;
+
+  /* Handle any BTF tags on the function itself.  */
+  if (btf_debuginfo_p ())
+handle_btf_tags (ctfc, die, function_type_id, -1);
 }
 
 /* Add CTF type record(s) for the given input DWARF DIE and return its type id.
@@ -928,6 +954,10 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
   break;
 }
 
+  /* Handle any BTF tags on the type.  */
+  if (btf_debuginfo_p () && !unrecog_die)
+handle_btf_tags (ctfc, die, type_id, -1);
+
   /* For all types unrepresented in CTF, use an explicit CTF type of kind
  CTF_K_UNKNOWN.  */
   if ((type_id == CTF_NULL_TYPEID) && (!unrecog_die))
@@ -936,6 +966,45 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
   return type_id;
 }
 
+/* BTF support.  Handle any BTF tags attached to a given DIE, and generate
+   intermediate CTF types for them.  */
+
+static void
+handle_btf_tags (ctf_container_ref ctfc, dw_die_ref die, ctf_id_t type_id,
+int component_idx)
+{
+  dw_die_ref c;
+  const char * name = NULL;
+  const char * value = NULL;
+
+  c = dw_get_die_child (die);
+  if (c)
+do
+  {
+   if (dw_get_die_tag (c) != DW_TAG_GNU_annotation)
+ {
+   c = dw_get_die_sib (c);
+   continue;
+ }
+
+   name = g

[PATCH 9/9] doc: document btf_decl_tag attribute

2023-07-11 Thread David Faust via Gcc-patches
Add documentation for the btf_decl_tag attribute.

gcc/

* doc/extend.texi (Common Function Attributes): Document btf_decl_tag.
(Common Variable Attributes): Likewise.
---
 gcc/doc/extend.texi | 47 +
 1 file changed, 47 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index d88fd75e06e..57923621c46 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2856,6 +2856,29 @@ declares that @code{my_alloc1} returns 16-byte aligned 
pointers and
 that @code{my_alloc2} returns a pointer whose value modulo 32 is equal
 to 8.
 
+@cindex @code{btf_decl_tag} function attribute
+@item btf_type_tag (@var{argument})
+The @code{btf_decl_tag} attribute may be used to associate (to ``tag'')
+function declarations with arbitrary strings.  Debugging information will
+be emitted to associate the @var{argument} string with the attributed function.
+In DWARF, a @code{DW_TAG_GNU_annotation} DIE will be emitted in the DWARF
+information as a child of the DIE for the function and holding the
+@var{argument} string.  In BTF, a @code{BTF_KIND_DECL_TAG} record is emitted
+in the .BTF ELF section.
+
+For example
+
+@smallexample
+extern int bar (char, int) __attribute__((btf_decl_tag("for_user")))
+@end smallexample
+
+associates the string ``for_user'' to the function ``bar''. This
+string will be recorded in the BTF and/or DWARF information associated
+with the function.
+
+The @code{btf_decl_tag} attribute can also be used on variables
+(@pxref{Common Variable Attributes})  and field declarations.
+
 @cindex @code{cold} function attribute
 @item cold
 The @code{cold} attribute on functions is used to inform the compiler that
@@ -7570,6 +7593,30 @@ This warning can be disabled by 
@option{-Wno-if-not-aligned}.
 The @code{warn_if_not_aligned} attribute can also be used for types
 (@pxref{Common Type Attributes}.)
 
+@cindex @code{btf_decl_tag} variable attribute
+@item btf_decl_tag (@var{argument})
+The @code{btf_decl_tag} attribute may be used to associate (to ``tag'')
+variable declarations with arbitrary strings.  Debugging information will
+be emitted to associate the @var{argument} string with the attributed variable.
+In DWARF, a @code{DW_TAG_GNU_annotation} DIE will be emitted in the DWARF
+information as a child of the DIE for the variable and holding the
+@var{argument} string.  In BTF, a @code{BTF_KIND_DECL_TAG} record is emitted
+in the .BTF ELF section.
+
+For example
+
+@smallexample
+int * foo __attribute__((btf_decl_tag("user")));
+@end smallexample
+
+@noindent
+associates the string ``user'' to the variable ``foo''. This string
+will be recorded in the BTF and/or DWARF information associated with
+the variable.
+
+The @code{btf_decl_tag} attribute can also be used on functions
+(@pxref{Common Function Attributes}) and field declarations.
+
 @cindex @code{strict_flex_array} variable attribute
 @item strict_flex_array (@var{level})
 The @code{strict_flex_array} attribute should be attached to the trailing
-- 
2.40.1



[PATCH 4/9] dwarf: expose get_die_parent

2023-07-11 Thread David Faust via Gcc-patches
Expose get_die_parent () so it can be used outside of dwarf2out.cc

gcc/

* dwarf2out.cc (get_die_parent): Make non-static.
* dwarf2out.h (get_die_parent): Add extern declaration here.
---
 gcc/dwarf2out.cc | 2 +-
 gcc/dwarf2out.h  | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index c8c34db2b5a..ba6d91f95cf 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -5457,7 +5457,7 @@ get_AT (dw_die_ref die, enum dwarf_attribute attr_kind)
 
 /* Returns the parent of the declaration of DIE.  */
 
-static dw_die_ref
+dw_die_ref
 get_die_parent (dw_die_ref die)
 {
   dw_die_ref t;
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 870b56a6a37..3be918edc21 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -453,6 +453,7 @@ extern dw_die_ref base_type_die (tree, bool);
 extern dw_die_ref lookup_decl_die (tree);
 extern dw_die_ref lookup_type_die (tree);
 
+extern dw_die_ref get_die_parent (dw_die_ref);
 extern dw_die_ref dw_get_die_child (dw_die_ref);
 extern dw_die_ref dw_get_die_sib (dw_die_ref);
 extern enum dwarf_tag dw_get_die_tag (dw_die_ref);
-- 
2.40.1



[PATCH 3/9] dwarf: create annotation DIEs for decl tags

2023-07-11 Thread David Faust via Gcc-patches
The "btf_decl_tag" attribute is handled by constructing a
DW_TAG_GNU_annotation DIE for each occurrence to record the argument
string in debug information. The DIEs are children of the declarations
they annotate, with the following format:

  DW_TAG_GNU_annotation
DW_AT_name "btf_decl_tag"
DW_AT_const_value 

gcc/

* dwarf2out.cc (gen_btf_decl_tag_dies): New function.
(gen_formal_parameter_die): Call it here.
(gen_decl_die): Likewise.
---
 gcc/dwarf2out.cc | 35 +++
 1 file changed, 35 insertions(+)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 238d0a94400..c8c34db2b5a 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -13620,6 +13620,35 @@ long_double_as_float128 (tree type)
   return NULL_TREE;
 }
 
+/* Given a tree T, which should be a decl, process any btf_decl_tag attributes
+   on T, provided in ATTR.  Construct DW_TAG_GNU_annotation DIEs appropriately
+   as children of TARGET, usually the DIE for T.  */
+
+static void
+gen_btf_decl_tag_dies (tree t, dw_die_ref target)
+{
+  dw_die_ref die;
+  tree attr;
+
+  if (t == NULL_TREE || !DECL_P (t) || !target)
+return;
+
+  attr = lookup_attribute ("btf_decl_tag", DECL_ATTRIBUTES (t));
+  while (attr != NULL_TREE)
+{
+  die = new_die (DW_TAG_GNU_annotation, target, t);
+  add_name_attribute (die, IDENTIFIER_POINTER (get_attribute_name (attr)));
+  add_AT_string (die, DW_AT_const_value,
+TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr;
+  attr = lookup_attribute ("btf_decl_tag", TREE_CHAIN (attr));
+}
+
+  /* Strip the decl tag attribute to avoid creating multiple copies if we hit
+ this tree node again in some recursive call.  */
+  DECL_ATTRIBUTES (t)
+= remove_attribute ("btf_decl_tag", DECL_ATTRIBUTES (t));
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
entry that chains the modifiers specified by CV_QUALS in front of the
given type.  REVERSE is true if the type is to be interpreted in the
@@ -23016,6 +23045,9 @@ gen_formal_parameter_die (tree node, tree origin, bool 
emit_name_p,
   gcc_unreachable ();
 }
 
+  /* Handle any attribute btf_decl_tag on the decl.  */
+  gen_btf_decl_tag_dies (node, parm_die);
+
   return parm_die;
 }
 
@@ -27170,6 +27202,9 @@ gen_decl_die (tree decl, tree origin, struct 
vlr_context *ctx,
   break;
 }
 
+  /* Handle any attribute btf_decl_tag on the decl.  */
+  gen_btf_decl_tag_dies (decl_or_origin, lookup_decl_die (decl_or_origin));
+
   return NULL;
 }
 
-- 
2.40.1



[PATCH 5/9] ctf: add support to pass through BTF tags

2023-07-11 Thread David Faust via Gcc-patches
BTF generation currently relies on the internal CTF representation to
convert debug info from DWARF dies. This patch adds a new internal
header, "ctf-int.h", which defines CTF kinds to be used internally to
represent BTF tags which must pass through the CTF container. It also
adds a new type for representing information specific to those tags, and
a member for that type in struct ctf_dtdef.

This patch also updates ctf_add_reftype to accept a const char * name,
and add it for the newly added type.

gcc/

* ctf-int.h: New file.
* ctfc.h: Include ctf-int.h.
(struct ctf_btf_annotation): New.
(struct ctf_dtdef): Add dtu_btfnote member to dtd_u union.
(enum ctf_dtu_d_union_enum): Add CTF_DTU_D_BTFNOTE.
(ctf_add_reftype): Add name argument.
* ctfc.cc (ctf_dtu_d_union_selector): Handle CTFC_INT_K_DECL_TAG.
(ctf_add_reftype): Add name argument. Pass it to ctf_add_generic.
(ctf_add_pointer): Update ctf_add_reftype call.
* btfout.cc (btf_init_postprocess): Update ctf_add_reftype call.
* dwarf2ctf.cc (gen_ctf_modifier_type): Update ctf_add_reftype call.
---
 gcc/btfout.cc|  2 +-
 gcc/ctf-int.h| 28 
 gcc/ctfc.cc  | 10 ++
 gcc/ctfc.h   | 17 ++---
 gcc/dwarf2ctf.cc |  2 +-
 5 files changed, 50 insertions(+), 9 deletions(-)
 create mode 100644 gcc/ctf-int.h

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index e07fed302c2..e6acf4e51a5 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -1302,7 +1302,7 @@ btf_init_postprocess (void)
 
  /* Create the 'const' modifier type for void.  */
  if (constvoid_id == CTF_NULL_TYPEID)
-   constvoid_id = ctf_add_reftype (tu_ctfc, CTF_ADD_ROOT,
+   constvoid_id = ctf_add_reftype (tu_ctfc, CTF_ADD_ROOT, NULL,
dvd->dvd_type, CTF_K_CONST, NULL);
  dvd->dvd_type = constvoid_id;
}
diff --git a/gcc/ctf-int.h b/gcc/ctf-int.h
new file mode 100644
index 000..d5586248f11
--- /dev/null
+++ b/gcc/ctf-int.h
@@ -0,0 +1,28 @@
+/* ctf-int.h - GCC internal definitions used for CTF debug info.
+   Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_CTF_INT_H
+#define GCC_CTF_INT_H 1
+
+/* This CTF kind exists only as a bridge to generating BTF types for
+   BTF_KIND_DECL_TAG.  It does not correspond to any representable type
+   kind in CTF.  */
+#define CTFC_INT_K_DECL_TAG  63
+
+#endif  /* GCC_CTF_INT_H */
diff --git a/gcc/ctfc.cc b/gcc/ctfc.cc
index ee569b12ac6..ccf090d0567 100644
--- a/gcc/ctfc.cc
+++ b/gcc/ctfc.cc
@@ -107,6 +107,8 @@ ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype)
   return CTF_DTU_D_ARGUMENTS;
 case CTF_K_SLICE:
   return CTF_DTU_D_SLICE;
+case CTFC_INT_K_DECL_TAG:
+  return CTF_DTU_D_BTFNOTE;
 default:
   /* The largest member as default.  */
   return CTF_DTU_D_ARRAY;
@@ -428,15 +430,15 @@ ctf_add_encoded (ctf_container_ref ctfc, uint32_t flag, 
const char * name,
 }
 
 ctf_id_t
-ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
-uint32_t kind, dw_die_ref die)
+ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, const char * name,
+ctf_id_t ref, uint32_t kind, dw_die_ref die)
 {
   ctf_dtdef_ref dtd;
   ctf_id_t type;
 
   gcc_assert (ref <= CTF_MAX_TYPE);
 
-  type = ctf_add_generic (ctfc, flag, NULL, &dtd, die);
+  type = ctf_add_generic (ctfc, flag, name, &dtd, die);
   dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0);
   /* Caller of this API must guarantee that a CTF type with id = ref already
  exists.  This will also be validated for us at link-time.  */
@@ -548,7 +550,7 @@ ctf_id_t
 ctf_add_pointer (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
 dw_die_ref die)
 {
-  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_POINTER, die));
+  return (ctf_add_reftype (ctfc, flag, NULL, ref, CTF_K_POINTER, die));
 }
 
 ctf_id_t
diff --git a/gcc/ctfc.h b/gcc/ctfc.h
index bf1841a7fcb..b9c6a44545b 100644
--- a/gcc/ctfc.h
+++ b/gcc/ctfc.h
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dwarf2ctf.h"
 #include "ctf.h"
 #include "btf.h"
+#include "ctf-int.h"
 
 /* Invalid CTF type ID definition.  */
 
@@ -151,6 +152,13 @@ typedef struct GTY (()) ctf_func_

[PATCH 2/9] include: add BTF decl tag defines

2023-07-11 Thread David Faust via Gcc-patches
Add definitions for btf_decl_tag and the DW_TAG_GNU_annotation
DWARF extension.

include/

* btf.h (struct btf_type): Update comment.
(BTF_KIND_DECL_TAG): New define.
(struct btf_decl_tag): New.
* dwarf2.def (DW_TAG_GNU_annotation): New DW_TAG extension.
---
 include/btf.h  | 14 +-
 include/dwarf2.def |  4 
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/include/btf.h b/include/btf.h
index d0994ab369b..bc808487ab8 100644
--- a/include/btf.h
+++ b/include/btf.h
@@ -69,7 +69,7 @@ struct btf_type
 
   /* SIZE is used by INT, ENUM, STRUCT, UNION, DATASEC kinds.
  TYPE is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, FUNC,
- FUNC_PROTO and VAR kinds.  */
+ FUNC_PROTO, VAR and DECL_TAG kinds.  */
   union
   {
 uint32_t size; /* Size of the entire type, in bytes.  */
@@ -109,6 +109,7 @@ struct btf_type
 #define BTF_KIND_VAR   14  /* Variable.  */
 #define BTF_KIND_DATASEC   15  /* Section such as .bss or .data.  */
 #define BTF_KIND_FLOAT 16  /* Floating point.  */
+#define BTF_KIND_DECL_TAG  17  /* Decl Tag.  */
 #define BTF_KIND_ENUM6419  /* Enumeration up to 64 bits.  */
 #define BTF_KIND_MAX   BTF_KIND_ENUM64
 #define NR_BTF_KINDS   (BTF_KIND_MAX + 1)
@@ -222,6 +223,17 @@ struct btf_enum64
   uint32_t val_hi32;   /* high 32-bit value for a 64-bit value Enumerator */
 };
 
+/* BTF_KIND_DECL_TAG is followed by a single struct btf_decl_tag, which
+   describes the tag location:
+   - If component_idx == -1, then the tag is applied to a struct, union,
+ variable or function.
+   - Otherwise it is applied to a struct/union member or function argument
+ with the given given index numbered 0..vlen-1.  */
+struct btf_decl_tag
+{
+  int32_t component_idx;
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 7ab3ee611fd..4351498f288 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -174,6 +174,10 @@ DW_TAG (DW_TAG_GNU_formal_parameter_pack, 0x4108)
are properly part of DWARF 5.  */
 DW_TAG (DW_TAG_GNU_call_site, 0x4109)
 DW_TAG (DW_TAG_GNU_call_site_parameter, 0x410a)
+
+/* Extension for BTF annotations.  */
+DW_TAG (DW_TAG_GNU_annotation, 0x6000)
+
 /* Extensions for UPC.  See: http://dwarfstd.org/doc/DWARF4.pdf.  */
 DW_TAG (DW_TAG_upc_shared_type, 0x8765)
 DW_TAG (DW_TAG_upc_strict_type, 0x8766)
-- 
2.40.1



[PATCH 0/9] Add btf_decl_tag C attribute

2023-07-11 Thread David Faust via Gcc-patches
Hello,

This series adds support for a new attribute, "btf_decl_tag" in GCC.
The same attribute is already supported in clang, and is used by various
components of the BPF ecosystem.

The purpose of the attribute is to allow to associate (to "tag")
declarations with arbitrary string annotations, which are emitted into
debugging information (DWARF and/or BTF) to facilitate post-compilation
analysis (the motivating use case being the Linux kernel BPF verifier).
Multiple tags are allowed on the same declaration.

These strings are not interpreted by the compiler, and the attribute
itself has no effect on generated code, other than to produce additional
DWARF DIEs and/or BTF records conveying the annotations.

This entails:

- A new C-language-level attribute which allows to associate (to "tag")
  particular declarations with arbitrary strings.

- The conveyance of that information in DWARF in the form of a new DIE,
  DW_TAG_GNU_annotation, with tag number (0x6000) and format matching
  that of the DW_TAG_LLVM_annotation extension supported in LLVM for
  the same purpose. These DIEs are already supported by BPF tooling,
  such as pahole.

- The conveyance of that information in BTF debug info in the form of
  BTF_KIND_DECL_TAG records. These records are already supported by
  LLVM and other tools in the eBPF ecosystem, such as the Linux kernel
  eBPF verifier.


Background
==

The purpose of these tags is to convey additional semantic information
to post-compilation consumers, in particular the Linux kernel eBPF
verifier. The verifier can make use of that information while analyzing
a BPF program to aid in determining whether to allow or reject the
program to be run. More background on these tags can be found in the
early support for them in the kernel here [1] and [2].

The "btf_decl_tag" attribute is half the story; the other half is a
sibling attribute "btf_type_tag" which serves the same purpose but
applies to types. Support for btf_type_tag will come in a separate
patch series, since it is impaced by GCC bug 110439 which needs to be
addressed first.

I submitted an initial version of this work (including btf_type_tag)
last spring [3], however at the time there were some open questions
about the behavior of the btf_type_tag attribute and issues with its
implementation. Since then we have clarified these details and agreed
to solutions with the BPF community and LLVM BPF folks.

The main motivation for emitting the tags in DWARF is that the Linux
kernel generates its BTF information via pahole, using DWARF as a source:

++  BTF  BTF   +--+
| pahole |---> vmlinux.btf --->| verifier |
++ +--+
^^
||
  DWARF |BTF |
||
  vmlinux  +-+
  module1.ko   | BPF program |
  module2.ko   +-+
...

This is because:

a)  pahole adds additional kernel-specific information into the
produced BTF based on additional analysis of kernel objects.

b)  Unlike GCC, LLVM will only generate BTF for BPF programs.

b)  GCC can generate BTF for whatever target with -gbtf, but there is no
support for linking/deduplicating BTF in the linker.

In the scenario above, the verifier needs access to the pointer tags of
both the kernel types/declarations (conveyed in the DWARF and translated
to BTF by pahole) and those of the BPF program (available directly in BTF).


DWARF Representation


As noted above, btf_decl_tag is represented in DWARF via a new DIE
DW_TAG_GNU_annotation, with identical format to the LLVM DWARF
extension DW_TAG_LLVM_annotation serving the same purpose. The DIE has
the following format:

  DW_TAG_GNU_annotation (0x6000)
DW_AT_name: "btf_decl_tag"
DW_AT_const_value: 

These DIEs are placed in the DWARF tree as children of the DIE for the
appropriate declaration, and one such DIE is created for each occurrence
of the btf_decl_tag attribute on a declaration.

For example:

  const int * c __attribute__((btf_decl_tag ("__c"), btf_decl_tag 
("devicemem")));

This declaration produces the following DWARF:

 <1><1e>: Abbrev Number: 2 (DW_TAG_variable)
<1f>   DW_AT_name: c
<24>   DW_AT_type: <0x49>
...
 <2><36>: Abbrev Number: 3 (User TAG value: 0x6000)
<37>   DW_AT_name: (indirect string, offset: 0x4c): btf_decl_tag
<3b>   DW_AT_const_value : (indirect string, offset: 0): devicemem
 <2><3f>: Abbrev Number: 4 (User TAG value: 0x6000)
<40>   DW_AT_name: (indirect string, offset: 0x4c): btf_decl_tag
<44>   DW_AT_const_value : __c
 <2><48>: Abbrev Number: 0
 <1><49>: Abbrev Number: 5 (DW_TAG_pointer_type)
 ...

The DIEs for btf_decl_tag are pla

[PATCH][committed] btf: fix bootstrap -Wformat errors [PR110073]

2023-06-02 Thread David Faust via Gcc-patches
Commit 7aae58b04b9 "btf: improve -dA comments for testsuite" broke
bootstrap on a number of architectures because it introduced some
new -Wformat errors.

Fix those errors by properly using PRIu64 and a small refactor to
the offending code.

Based on the suggested patch from Rainer Orth.
Committed as obvious.

PR debug/110073

gcc/ChangeLog:

* btfout.cc (btf_absolute_func_id): New function.
(btf_asm_func_type): Call it here.  Change index parameter from
size_t to ctf_id_t.  Use PRIu64 formatter.
---
 gcc/btfout.cc | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 1ea68b9e8ba..e07fed302c2 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -192,6 +192,14 @@ btf_relative_var_id (ctf_id_t abs)
   return abs - (num_types_added + 1);
 }
 
+/* Return the final BTF ID of the func record at relative index REL.  */
+
+static ctf_id_t
+btf_absolute_func_id (ctf_id_t rel)
+{
+  return rel + (num_types_added + 1) + num_vars_added;
+}
+
 /* Return the relative index of the func record with final BTF ID ABS.  */
 
 static ctf_id_t
@@ -937,13 +945,12 @@ btf_asm_func_arg (ctf_container_ref ctfc, ctf_func_arg_t 
* farg,
 /* Asm'out a BTF_KIND_FUNC type.  */
 
 static void
-btf_asm_func_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd, size_t i)
+btf_asm_func_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd, ctf_id_t id)
 {
   ctf_id_t ref_id = dtd->dtd_data.ctti_type;
   dw2_asm_output_data (4, dtd->dtd_data.ctti_name,
-  "TYPE %lu BTF_KIND_FUNC '%s'",
-  num_types_added + num_vars_added + 1 + i,
-  dtd->dtd_name);
+  "TYPE %" PRIu64 " BTF_KIND_FUNC '%s'",
+  btf_absolute_func_id (id), dtd->dtd_name);
   dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_FUNC, 0, dtd->linkage),
   "btt_info: kind=%u, kflag=%u, linkage=%u",
   BTF_KIND_FUNC, 0, dtd->linkage);
-- 
2.40.1



[PATCH 2/2] btf: improve -dA comments for testsuite

2023-05-30 Thread David Faust via Gcc-patches
[Changes from v1:
 - Fix typos.
 - Split unrelated change into separate commit.
 - Improve asm comment for enum constants, update btf-enum-1 test.
 - Improve asm comment for DATASEC records, update btf-datasec-2 test.]

Many BTF type kinds refer to other types via index to the final types
list. However, the order of the final types list is not guaranteed to
remain the same for the same source program between different runs of
the compiler, making it difficult to test inter-type references.

This patch updates the assembler comments output when writing a
given BTF record to include minimal information about the referenced
type, if any. This allows for the regular expressions used in the gcc
testsuite to do some basic integrity checks on inter-type references.

For example, for the type

unsigned int *

Assembly comments like the following are written with -dA:

.4byte  0   ; TYPE 2 BTF_KIND_PTR ''
.4byte  0x200   ; btt_info: kind=2, kflag=0, vlen=0
.4byte  0x1 ; btt_type: (BTF_KIND_INT 'unsigned int')

Several BTF tests which can immediately be made more robust with this
change are updated. It will also be useful in new tests for the upcoming
btf_type_tag support.

Re-tested on BPF and x86_64, no known regressions.
Thanks.

gcc/

* btfout.cc (btf_kind_names): New.
(btf_kind_name): New.
(btf_absolute_var_id): New utility function.
(btf_relative_var_id): Likewise.
(btf_relative_func_id): Likewise.
(btf_absolute_datasec_id): Likewise.
(btf_asm_type_ref): New.
(btf_asm_type): Update asm comments and use btf_asm_type_ref ().
(btf_asm_array): Likewise. Accept ctf_container_ref parameter.
(btf_asm_varent): Likewise.
(btf_asm_func_arg): Likewise.
(btf_asm_datasec_entry): Likewise.
(btf_asm_datasec_type): Likewise.
(btf_asm_func_type): Likewise. Add index parameter.
(btf_asm_enum_const): Likewise.
(btf_asm_sou_member): Likewise.
(output_btf_vars): Update btf_asm_* call accordingly.
(output_asm_btf_sou_fields): Likewise.
(output_asm_btf_enum_list): Likewise.
(output_asm_btf_func_args_list): Likewise.
(output_asm_btf_vlen_bytes): Likewise.
(output_btf_func_types): Add ctf_container_ref parameter.
Pass it to btf_asm_func_type.
(output_btf_datasec_types): Update btf_asm_datsec_type call similarly.
(btf_output): Update output_btf_func_types call similarly.

gcc/testsuite/

* gcc.dg/debug/btf/btf-array-1.c: Use new BTF asm comments
in scan-assembler expressions where useful.
* gcc.dg/debug/btf/btf-anonymous-struct-1.c: Likewise.
* gcc.dg/debug/btf/btf-anonymous-union-1.c: Likewise.
* gcc.dg/debug/btf/btf-bitfields-2.c: Likewise.
* gcc.dg/debug/btf/btf-bitfields-3.c: Likewise.
* gcc.dg/debug/btf/btf-datasec-2.c: Likewise.
* gcc.dg/debug/btf/btf-enum-1.c: Likewise.
* gcc.dg/debug/btf/btf-function-6.c: Likewise.
* gcc.dg/debug/btf/btf-pointers-1.c: Likewise.
* gcc.dg/debug/btf/btf-struct-1.c: Likewise.
* gcc.dg/debug/btf/btf-struct-2.c: Likewise.
* gcc.dg/debug/btf/btf-typedef-1.c: Likewise.
* gcc.dg/debug/btf/btf-union-1.c: Likewise.
* gcc.dg/debug/btf/btf-variables-1.c: Likewise.
* gcc.dg/debug/btf/btf-variables-2.c: Likewise. Update outdated comment.
* gcc.dg/debug/btf/btf-function-3.c: Update outdated comment.
---
 gcc/btfout.cc | 227 ++
 .../gcc.dg/debug/btf/btf-anonymous-struct-1.c |   3 +-
 .../gcc.dg/debug/btf/btf-anonymous-union-1.c  |   4 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-array-1.c  |   3 +
 .../gcc.dg/debug/btf/btf-bitfields-2.c|   2 +-
 .../gcc.dg/debug/btf/btf-bitfields-3.c|   2 +-
 .../gcc.dg/debug/btf/btf-datasec-2.c  |   4 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-enum-1.c   |   4 +
 .../gcc.dg/debug/btf/btf-function-3.c |   2 +-
 .../gcc.dg/debug/btf/btf-function-6.c |   4 +-
 .../gcc.dg/debug/btf/btf-pointers-1.c |   3 +
 gcc/testsuite/gcc.dg/debug/btf/btf-struct-1.c |   4 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c |   2 +-
 .../gcc.dg/debug/btf/btf-typedef-1.c  |  14 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-union-1.c  |   2 +-
 .../gcc.dg/debug/btf/btf-variables-1.c|   6 +
 .../gcc.dg/debug/btf/btf-variables-2.c|   7 +-
 17 files changed, 224 insertions(+), 69 deletions(-)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index ae9855716eb..f51ccf73242 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -114,6 +114,23 @@ static unsigned int num_types_added = 0;
CTF types.  */
 static unsigned int num_types_created = 0;
 
+/* Name strings for BTF kinds.
+   Note: the indices here must match the type defines in btf.h.  */
+static const char *const btf_kind_names[] =
+  {
+"UNKN", "INT", "PTR", "ARRAY", "STR

[PATCH 1/2] btf: be clear when record size/type is not used

2023-05-30 Thread David Faust via Gcc-patches
[Changes from v1: split this change into own commit.]

All BTF type records have a 4-byte field used to encode a size or link
to another type, depending on the type kind. But BTF_KIND_ARRAY and
BTF_KIND_FWD do not use this field at all, and should write zero.

GCC already correctly writes zero in this field for these type kinds,
but the process is not straightforward and results in the -dA comment
claiming the field is a reference to another type. This patch makes
the behavior explicit and updates the assembler comment to state
clearly that the field is unused.

gcc/

* btfout.cc (btf_asm_type): Add dedicated cases for BTF_KIND_ARRAY
and BTF_KIND_FWD which do not use the size/type field at all.
---
 gcc/btfout.cc | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 497c1ca06e6..ae9855716eb 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -705,6 +705,12 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
   dw2_asm_output_data (4, dtd->dtd_data.ctti_size, "btt_size: %uB",
   dtd->dtd_data.ctti_size);
   return;
+case BTF_KIND_ARRAY:
+case BTF_KIND_FWD:
+  /* These types do not encode any information in the size/type field
+and should write 0.  */
+  dw2_asm_output_data (4, 0, "(unused)");
+  return;
 default:
   break;
 }
-- 
2.40.1



Re: [PATCH] btf: improve -dA comments for testsuite

2023-05-30 Thread David Faust via Gcc-patches



On 5/30/23 00:30, Indu Bhagat wrote:
> On 5/25/23 9:37 AM, David Faust via Gcc-patches wrote:
>> Many BTF type kinds refer to other types via index to the final types
>> list. However, the order of the final types list is not guaranteed to
>> remain the same for the same source program between different runs of
>> the compiler, making it difficult to test inter-type references.
>>
>> This patch updates the assembler comments output when writing a
>> given BTF record to include minimal information about the referenced
>> type, if any. This allows for the regular expressions used in the gcc
>> testsuite to do some basic integrity checks on inter-type references.
>>
>> For example, for the type
>>
>>  unsigned int *
>>
>> Assembly comments like the following are written with -dA:
>>
>>  .4byte  0   ; TYPE 2 BTF_KIND_PTR ''
>>  .4byte  0x200   ; btt_info: kind=2, kflag=0, vlen=0
>>  .4byte  0x1 ; btt_type: (BTF_KIND_INT 'unsigned int')
>>
>> Several BTF tests which can immediately be made more robust with this
>> change are updated. It will also be useful in new tests for the upcoming
>> btf_type_tag support.
>>
> 
> Thanks for working on this, David.  It will be nice to use these 
> enhanced assembler comments in the output for some of CTF testing as 
> well sometime.  But we can get to that later after this comit.
> 
> Some comments inlined below.
> 
>> Tested on BPF and x86_64, no known regressions.
>> OK for trunk?
>>
>> Thanks.
>>
>> gcc/
>>
>>  * btfout.cc (btf_kind_names): New.
>>  (btf_kind_name): New.
>>  (btf_absolute_var_id): New utility function.
>>  (btf_relative_var_id): Likewise.
>>  (btf_relative_func_id): Likewise.
>>  (btf_absolute_datasec_id): Likewise.
>>  (btf_asm_type_ref): New.
>>  (btf_asm_type): Update asm comments and use btf_asm_type_ref ().
>>  (btf_asm_array): Likewise. Accept ctf_container_ref parameter.
>>  (btf_asm_varent): Likewise.
>>  (btf_asm_func_arg): Likewise.
>>  (btf_asm_datasec_entry): Likewise.
>>  (btf_asm_datasec_type): Likewise.
>>  (btf_asm_func_type): Likewise. Add index parameter.
>>  (btf_asm_sou_member): Likewise.
>>  (output_btf_vars): Update btf_asm_* call accordingly.
>>  (output_asm_btf_sou_fields): Likewise.
>>  (output_asm_btf_func_args_list): Likewise.
>>  (output_asm_btf_vlen_bytes): Likewise.
>>  (output_btf_func_types): Add ctf_container_ref parameter.
>>  Pass it to btf_asm_func_type.
>>  (output_btf_datasec_types): Update btf_asm_datsec_type call similarly.
>>  (btf_output): Update output_btf_func_types call similarly.
>>
>> gcc/testsuite/
>>
>>  * gcc.dg/debug/btf/btf-array-1.c: Use new BTF asm comments
>>  in scan-assembler expressions where useful.
>>  * gcc.dg/debug/btf/btf-anonymous-struct-1.c: Likewise.
>>  * gcc.dg/debug/btf/btf-anonymous-union-1.c: Likewise.
>>  * gcc.dg/debug/btf/btf-bitfields-2.c: Likewise.
>>  * gcc.dg/debug/btf/btf-bitfields-3.c: Likewise.
>>  * gcc.dg/debug/btf/btf-function-6.c: Likewise.
>>  * gcc.dg/debug/btf/btf-pointers-1.c: Likewise.
>>  * gcc.dg/debug/btf/btf-struct-1.c: Likewise.
>>  * gcc.dg/debug/btf/btf-struct-2.c: Likewise.
>>  * gcc.dg/debug/btf/btf-typedef-1.c: Likewise.
>>  * gcc.dg/debug/btf/btf-union-1.c: Likewise.
>>  * gcc.dg/debug/btf/btf-variables-1.c: Likewise.
>>  * gcc.dg/debug/btf/btf-variables-2.c: Likewise. Update outdated comment.
>>  * gcc.dg/debug/btf/btf-function-3.c: Update outdated comment.
>> ---
>>   gcc/btfout.cc | 220 ++
>>   .../gcc.dg/debug/btf/btf-anonymous-struct-1.c |   3 +-
>>   .../gcc.dg/debug/btf/btf-anonymous-union-1.c  |   4 +-
>>   gcc/testsuite/gcc.dg/debug/btf/btf-array-1.c  |   3 +
>>   .../gcc.dg/debug/btf/btf-bitfields-2.c|   2 +-
>>   .../gcc.dg/debug/btf/btf-bitfields-3.c|   2 +-
>>   .../gcc.dg/debug/btf/btf-function-3.c |   2 +-
>>   .../gcc.dg/debug/btf/btf-function-6.c |   4 +-
>>   .../gcc.dg/debug/btf/btf-pointers-1.c |   3 +
>>   gcc/testsuite/gcc.dg/debug/btf/btf-struct-1.c |   4 +-
>>   gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c |   2 +-
>>   .../gcc.dg/debug/btf/btf-typedef-1.c  |  14 +-
>>   gcc/testsuite/gcc.dg/debug/btf/btf-union-1.c  |   2 +-
>>   .../gcc.dg/debug/btf/btf-variables-1.c|   6 +
>>   ..

[PATCH] btf: improve -dA comments for testsuite

2023-05-25 Thread David Faust via Gcc-patches
Many BTF type kinds refer to other types via index to the final types
list. However, the order of the final types list is not guaranteed to
remain the same for the same source program between different runs of
the compiler, making it difficult to test inter-type references.

This patch updates the assembler comments output when writing a
given BTF record to include minimal information about the referenced
type, if any. This allows for the regular expressions used in the gcc
testsuite to do some basic integrity checks on inter-type references.

For example, for the type

unsigned int *

Assembly comments like the following are written with -dA:

.4byte  0   ; TYPE 2 BTF_KIND_PTR ''
.4byte  0x200   ; btt_info: kind=2, kflag=0, vlen=0
.4byte  0x1 ; btt_type: (BTF_KIND_INT 'unsigned int')

Several BTF tests which can immediately be made more robust with this
change are updated. It will also be useful in new tests for the upcoming
btf_type_tag support.

Tested on BPF and x86_64, no known regressions.
OK for trunk?

Thanks.

gcc/

* btfout.cc (btf_kind_names): New.
(btf_kind_name): New.
(btf_absolute_var_id): New utility function.
(btf_relative_var_id): Likewise.
(btf_relative_func_id): Likewise.
(btf_absolute_datasec_id): Likewise.
(btf_asm_type_ref): New.
(btf_asm_type): Update asm comments and use btf_asm_type_ref ().
(btf_asm_array): Likewise. Accept ctf_container_ref parameter.
(btf_asm_varent): Likewise.
(btf_asm_func_arg): Likewise.
(btf_asm_datasec_entry): Likewise.
(btf_asm_datasec_type): Likewise.
(btf_asm_func_type): Likewise. Add index parameter.
(btf_asm_sou_member): Likewise.
(output_btf_vars): Update btf_asm_* call accordingly.
(output_asm_btf_sou_fields): Likewise.
(output_asm_btf_func_args_list): Likewise.
(output_asm_btf_vlen_bytes): Likewise.
(output_btf_func_types): Add ctf_container_ref parameter.
Pass it to btf_asm_func_type.
(output_btf_datasec_types): Update btf_asm_datsec_type call similarly.
(btf_output): Update output_btf_func_types call similarly.

gcc/testsuite/

* gcc.dg/debug/btf/btf-array-1.c: Use new BTF asm comments
in scan-assembler expressions where useful.
* gcc.dg/debug/btf/btf-anonymous-struct-1.c: Likewise.
* gcc.dg/debug/btf/btf-anonymous-union-1.c: Likewise.
* gcc.dg/debug/btf/btf-bitfields-2.c: Likewise.
* gcc.dg/debug/btf/btf-bitfields-3.c: Likewise.
* gcc.dg/debug/btf/btf-function-6.c: Likewise.
* gcc.dg/debug/btf/btf-pointers-1.c: Likewise.
* gcc.dg/debug/btf/btf-struct-1.c: Likewise.
* gcc.dg/debug/btf/btf-struct-2.c: Likewise.
* gcc.dg/debug/btf/btf-typedef-1.c: Likewise.
* gcc.dg/debug/btf/btf-union-1.c: Likewise.
* gcc.dg/debug/btf/btf-variables-1.c: Likewise.
* gcc.dg/debug/btf/btf-variables-2.c: Likewise. Update outdated comment.
* gcc.dg/debug/btf/btf-function-3.c: Update outdated comment.
---
 gcc/btfout.cc | 220 ++
 .../gcc.dg/debug/btf/btf-anonymous-struct-1.c |   3 +-
 .../gcc.dg/debug/btf/btf-anonymous-union-1.c  |   4 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-array-1.c  |   3 +
 .../gcc.dg/debug/btf/btf-bitfields-2.c|   2 +-
 .../gcc.dg/debug/btf/btf-bitfields-3.c|   2 +-
 .../gcc.dg/debug/btf/btf-function-3.c |   2 +-
 .../gcc.dg/debug/btf/btf-function-6.c |   4 +-
 .../gcc.dg/debug/btf/btf-pointers-1.c |   3 +
 gcc/testsuite/gcc.dg/debug/btf/btf-struct-1.c |   4 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-struct-2.c |   2 +-
 .../gcc.dg/debug/btf/btf-typedef-1.c  |  14 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-union-1.c  |   2 +-
 .../gcc.dg/debug/btf/btf-variables-1.c|   6 +
 .../gcc.dg/debug/btf/btf-variables-2.c|   7 +-
 15 files changed, 215 insertions(+), 63 deletions(-)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 497c1ca06e6..8960acfbbaa 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -114,6 +114,23 @@ static unsigned int num_types_added = 0;
CTF types.  */
 static unsigned int num_types_created = 0;
 
+/* Name strings for BTF kinds.
+   Note: the indices here must match the type defines in btf.h.  */
+static const char *const btf_kind_names[] =
+  {
+"UNKN", "INT", "PTR", "ARRAY", "STRUCT", "UNION", "ENUM", "FWD",
+"TYPEDEF", "VOLATILE", "CONST", "RESTRICT", "FUNC", "FUNC_PROTO",
+"VAR", "DATASEC", "FLOAT", "DECL_TAG", "TYPE_TAG", "ENUM64"
+  };
+
+/* Return a name string for the given BTF_KIND.  */
+
+static const char *
+btf_kind_name (uint32_t btf_kind)
+{
+  return btf_kind_names[btf_kind];
+}
+
 /* Map a CTF type kind to the corresponding BTF type kind.  */
 
 static uint32_t
@@ -141,6 +158,57 @@ get_btf_kind (uint32_t ctf_kind)
   return BTF_KIND_UNKN;
 }
 
+/* Helper rou

[PATCH] bpf: fix memory constraint of ldx/stx instructions [PR108790]

2023-02-14 Thread David Faust via Gcc-patches
In some cases where the target memory address for an ldx or stx
instruction could be reduced to a constant, GCC could emit a malformed
instruction like:

ldxdw %r0,0

Rather than the expected form:

ldxdw %rX, [%rY + OFFSET]

This is due to the constraint allowing a const_int operand, which the
output templates do not handle.

Fix it by introducing a new memory constraint for the appropriate
operands of these instructions, which is identical to 'm' except that
it does not accept const_int.

Tested with bpf-unknown-none, no known regressions.
OK?

Thanks.

gcc/

PR target/108790
* config/bpf/constraints.md (q): New memory constraint.
* config/bpf/bpf.md (zero_extendhidi2): Use it here.
(zero_extendqidi2): Likewise.
(zero_extendsidi2): Likewise.
(*mov): Likewise.

gcc/testsuite/

PR target/108790
* gcc.target/bpf/ldxdw.c: New test.
---
 gcc/config/bpf/bpf.md| 10 +-
 gcc/config/bpf/constraints.md| 11 +++
 gcc/testsuite/gcc.target/bpf/ldxdw.c | 12 
 3 files changed, 28 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/ldxdw.c

diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index d9af98384ef..f6be0a21234 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -242,7 +242,7 @@ (define_insn "xor3"
 
 (define_insn "zero_extendhidi2"
   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
-   (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "0,r,m")))]
+   (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "0,r,q")))]
   ""
   "@
and\t%0,0x
@@ -252,7 +252,7 @@ (define_insn "zero_extendhidi2"
 
 (define_insn "zero_extendqidi2"
   [(set (match_operand:DI 0 "register_operand" "=r,r,r")
-   (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "0,r,m")))]
+   (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "0,r,q")))]
   ""
   "@
and\t%0,0xff
@@ -263,7 +263,7 @@ (define_insn "zero_extendqidi2"
 (define_insn "zero_extendsidi2"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
(zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
+ (match_operand:SI 1 "nonimmediate_operand" "r,q")))]
   ""
   "@
* return bpf_has_alu32 ? \"mov32\t%0,%1\" : 
\"mov\t%0,%1\;and\t%0,0x\";
@@ -302,8 +302,8 @@ (define_expand "mov"
 }")
 
 (define_insn "*mov"
-  [(set (match_operand:MM 0 "nonimmediate_operand" "=r, r,r,m,m")
-(match_operand:MM 1 "mov_src_operand"  " m,rI,B,r,I"))]
+  [(set (match_operand:MM 0 "nonimmediate_operand" "=r, r,r,q,q")
+(match_operand:MM 1 "mov_src_operand"  " q,rI,B,r,I"))]
   ""
   "@
ldx\t%0,%1
diff --git a/gcc/config/bpf/constraints.md b/gcc/config/bpf/constraints.md
index c8a65cfcddb..33f9177b8eb 100644
--- a/gcc/config/bpf/constraints.md
+++ b/gcc/config/bpf/constraints.md
@@ -29,3 +29,14 @@ (define_constraint "B"
 (define_constraint "S"
   "A constant call address."
   (match_code "const,symbol_ref,label_ref,const_int"))
+
+;;
+;; Memory constraints.
+;;
+
+; Just like 'm' but disallows const_int.
+; Used for ldx[b,h,w,dw] and stx[b,h,w,dw] instructions.
+(define_memory_constraint "q"
+  "Memory reference which is not a constant integer."
+  (and (match_code "mem")
+   (match_test "GET_CODE(XEXP(op, 0)) != CONST_INT")))
diff --git a/gcc/testsuite/gcc.target/bpf/ldxdw.c 
b/gcc/testsuite/gcc.target/bpf/ldxdw.c
new file mode 100644
index 000..0985ea3e6ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/ldxdw.c
@@ -0,0 +1,12 @@
+/* Verify that we do not generate a malformed ldxdw instruction
+   with a constant instead of register + offset.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-times "ldxdw\t%r.,\\\[%r.+0\\\]" 1 } } */
+/* { dg-final { scan-assembler-not "ldxdw\t%r.,\[0-9\]+" } } */
+
+unsigned long long test () {
+  return *((unsigned long long *) 0x4000);
+}
-- 
2.39.0



[PATCH v2] bpf: correct bpf_print_operand for floats [PR108293]

2023-01-10 Thread David Faust via Gcc-patches
Hi Jose,

As we discussed on IRC, since we don't currently define
TARGET_SUPPORTS_WIDE_INT it is safer to keep the handling for VOIDmode
CONST_DOUBLEs. My current understanding is that it may be needed if the
host is a 32-bit platform.

I also added a gcc_unreachable () as you pointed out. V2 below.
Tested with bpf-unknown-none on x86_64 host, no known regressions.

WDYT?

Thanks,
David

---

[Changes from v1:
 - Keep handling for VOIDmode CONST_DOUBLE, just in case.
 - Add a gcc_unreachable () if `op` is none of VOIDmode, SFmode,
   nor DFmode. ]

The existing logic in bpf_print_operand was only correct for integral
CONST_DOUBLEs, and emitted garbage for floating point modes. Fix it so
floating point mode operands are correctly handled.

PR target/108293

gcc/

* config/bpf/bpf.cc (bpf_print_operand): Correct handling for
floating point modes.

gcc/testsuite/

* gcc.target/bpf/double-1.c: New test.
* gcc.target/bpf/double-2.c: New test.
* gcc.target/bpf/float-1.c: New test.
---
 gcc/config/bpf/bpf.cc   | 34 -
 gcc/testsuite/gcc.target/bpf/double-1.c | 12 +
 gcc/testsuite/gcc.target/bpf/double-2.c | 12 +
 gcc/testsuite/gcc.target/bpf/float-1.c  | 12 +
 4 files changed, 64 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/double-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/double-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/float-1.c

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 2aeaeaf309b..576a1fe8eab 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -880,13 +880,35 @@ bpf_print_operand (FILE *file, rtx op, int code 
ATTRIBUTE_UNUSED)
   output_address (GET_MODE (op), XEXP (op, 0));
   break;
 case CONST_DOUBLE:
-  if (CONST_DOUBLE_HIGH (op))
-   fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
-CONST_DOUBLE_HIGH (op), CONST_DOUBLE_LOW (op));
-  else if (CONST_DOUBLE_LOW (op) < 0)
-   fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (op));
+  if (GET_MODE (op) == VOIDmode)
+   {
+ if (CONST_DOUBLE_HIGH (op))
+   fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
+CONST_DOUBLE_HIGH (op), CONST_DOUBLE_LOW (op));
+ else if (CONST_DOUBLE_LOW (op) < 0)
+   fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (op));
+ else
+   fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (op));
+   }
   else
-   fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (op));
+   {
+ long vals[2];
+ real_to_target (vals, CONST_DOUBLE_REAL_VALUE (op), GET_MODE (op));
+ vals[0] &= 0x;
+ vals[1] &= 0x;
+ if (GET_MODE (op) == SFmode)
+   fprintf (file, "0x%08lx", vals[0]);
+ else if (GET_MODE (op) == DFmode)
+   {
+ /* Note: real_to_target puts vals in target word order.  */
+ if (WORDS_BIG_ENDIAN)
+   fprintf (file, "0x%08lx%08lx", vals[0], vals[1]);
+ else
+   fprintf (file, "0x%08lx%08lx", vals[1], vals[0]);
+   }
+ else
+   gcc_unreachable ();
+   }
   break;
 default:
   output_addr_const (file, op);
diff --git a/gcc/testsuite/gcc.target/bpf/double-1.c 
b/gcc/testsuite/gcc.target/bpf/double-1.c
new file mode 100644
index 000..200f1bd18f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/double-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mlittle-endian" } */
+
+double f;
+double a() { f = 1.0; return 1.0; }
+double b() { f = 2.0; return 2.0; }
+double c() { f = 2.0; return 3.0; }
+double d() { f = 3.0; return 3.0; }
+
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x3ff0" 2 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4000" 3 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4008" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/double-2.c 
b/gcc/testsuite/gcc.target/bpf/double-2.c
new file mode 100644
index 000..d04ddd0c575
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/double-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mbig-endian" } */
+
+double f;
+double a() { f = 1.0; return 1.0; }
+double b() { f = 2.0; return 2.0; }
+double c() { f = 2.0; return 3.0; }
+double d() { f = 3.0; return 3.0; }
+
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x3ff0" 2 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4000" 3 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4008" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/float-1.c 
b/gcc/testsuite/gcc.target/bpf/float-1.c
new file mode 100644
index 000..05ed7bb651d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/float-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mlitt

[PATCH] bpf: correct bpf_print_operand for floats [PR108293]

2023-01-09 Thread David Faust via Gcc-patches
The existing logic in bpf_print_operand was only correct for integral
CONST_DOUBLEs, and emitted garbage for floating point modes. Fix it so
floating point mode operands are correctly handled.

Tested on bpf-unknown-none, no known regressions.
OK to check-in?

Thanks.


PR target/108293

gcc/

* config/bpf/bpf.cc (bpf_print_operand): Correct handling for
floating point modes.

gcc/testsuite/

* gcc.target/bpf/double-1.c: New test.
* gcc.target/bpf/double-2.c: New test.
* gcc.target/bpf/float-1.c: New test.
---
 gcc/config/bpf/bpf.cc   | 21 ++---
 gcc/testsuite/gcc.target/bpf/double-1.c | 12 
 gcc/testsuite/gcc.target/bpf/double-2.c | 12 
 gcc/testsuite/gcc.target/bpf/float-1.c  | 12 
 4 files changed, 50 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/double-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/double-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/float-1.c

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 2aeaeaf309b..9dde3944e9c 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -880,13 +880,20 @@ bpf_print_operand (FILE *file, rtx op, int code 
ATTRIBUTE_UNUSED)
   output_address (GET_MODE (op), XEXP (op, 0));
   break;
 case CONST_DOUBLE:
-  if (CONST_DOUBLE_HIGH (op))
-   fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
-CONST_DOUBLE_HIGH (op), CONST_DOUBLE_LOW (op));
-  else if (CONST_DOUBLE_LOW (op) < 0)
-   fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (op));
-  else
-   fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (op));
+  long vals[2];
+  real_to_target (vals, CONST_DOUBLE_REAL_VALUE (op), GET_MODE (op));
+  vals[0] &= 0x;
+  vals[1] &= 0x;
+  if (GET_MODE (op) == SFmode)
+   fprintf (file, "0x%08lx", vals[0]);
+  else if (GET_MODE (op) == DFmode)
+   {
+ /* Note: real_to_target puts vals in target word order.  */
+ if (WORDS_BIG_ENDIAN)
+   fprintf (file, "0x%08lx%08lx", vals[0], vals[1]);
+ else
+   fprintf (file, "0x%08lx%08lx", vals[1], vals[0]);
+   }
   break;
 default:
   output_addr_const (file, op);
diff --git a/gcc/testsuite/gcc.target/bpf/double-1.c 
b/gcc/testsuite/gcc.target/bpf/double-1.c
new file mode 100644
index 000..200f1bd18f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/double-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mlittle-endian" } */
+
+double f;
+double a() { f = 1.0; return 1.0; }
+double b() { f = 2.0; return 2.0; }
+double c() { f = 2.0; return 3.0; }
+double d() { f = 3.0; return 3.0; }
+
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x3ff0" 2 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4000" 3 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4008" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/double-2.c 
b/gcc/testsuite/gcc.target/bpf/double-2.c
new file mode 100644
index 000..d04ddd0c575
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/double-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mbig-endian" } */
+
+double f;
+double a() { f = 1.0; return 1.0; }
+double b() { f = 2.0; return 2.0; }
+double c() { f = 2.0; return 3.0; }
+double d() { f = 3.0; return 3.0; }
+
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x3ff0" 2 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4000" 3 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4008" 3 } } */
diff --git a/gcc/testsuite/gcc.target/bpf/float-1.c 
b/gcc/testsuite/gcc.target/bpf/float-1.c
new file mode 100644
index 000..05ed7bb651d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/float-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-mlittle-endian" } */
+
+float f;
+float a() { f = 1.0; return 1.0; }
+float b() { f = 2.0; return 2.0; }
+float c() { f = 2.0; return 3.0; }
+float d() { f = 3.0; return 3.0; }
+
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x3f80" 2 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4000" 3 } } */
+/* { dg-final { scan-assembler-times "lddw\t%r.,0x4040" 3 } } */
-- 
2.39.0



[PATCH v2 3/3] btf: correct generation for extern funcs [PR106773]

2022-12-13 Thread David Faust via Gcc-patches
[Changes from v1:
 - Add enum btf_func_linkage to include/btf.h and use it.
 - Minor updates to comments based on review. ]

The eBPF loader expects to find entries for functions declared as extern
in the corresponding BTF_KIND_DATASEC record, but we were not generating
these entries.

This patch adds support for the 'extern' linkage of function types in
BTF, and creates entries for for them BTF_KIND_DATASEC records as needed.

PR target/106773

gcc/

* btfout.cc (get_section_name): New function.
(btf_collect_datasec): Use it here. Process functions, marking them
'extern' and generating DATASEC entries for them as appropriate. Move
creation of BTF_KIND_FUNC records to here...
(btf_dtd_emit_preprocess_cb): ... from here.

gcc/testsuite/

* gcc.dg/debug/btf/btf-datasec-2.c: New test.
* gcc.dg/debug/btf/btf-function-6.c: New test.

include/

* btf.h (enum btf_func_linkage): New.
(struct btf_var_secinfo): Update comments with notes about extern
functions.
---
 gcc/btfout.cc | 129 --
 .../gcc.dg/debug/btf/btf-datasec-2.c  |  28 
 .../gcc.dg/debug/btf/btf-function-6.c |  19 +++
 include/btf.h |  18 ++-
 4 files changed, 148 insertions(+), 46 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-datasec-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-function-6.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 204b11d4e9f..a423fabc0b5 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -290,7 +290,35 @@ btf_datasec_push_entry (ctf_container_ref ctfc, const char 
*secname,
   ds.entries.safe_push (info);
 
   datasecs.safe_push (ds);
-  num_types_created++;
+}
+
+
+/* Return the section name, as of interest to btf_collect_datasec, for the
+   given symtab node.  Note that this deliberately returns NULL for objects
+   which do not go in a section btf_collect_datasec cares about.  */
+static const char *
+get_section_name (symtab_node *node)
+{
+  const char *section_name = node->get_section ();
+
+  if (section_name == NULL)
+{
+  switch (categorize_decl_for_section (node->decl, 0))
+   {
+   case SECCAT_BSS:
+ section_name = ".bss";
+ break;
+   case SECCAT_DATA:
+ section_name = ".data";
+ break;
+   case SECCAT_RODATA:
+ section_name = ".rodata";
+ break;
+   default:;
+   }
+}
+
+  return section_name;
 }
 
 /* Construct all BTF_KIND_DATASEC records for CTFC. One such record is created
@@ -301,7 +329,60 @@ btf_datasec_push_entry (ctf_container_ref ctfc, const char 
*secname,
 static void
 btf_collect_datasec (ctf_container_ref ctfc)
 {
-  /* See cgraph.h struct symtab_node, which varpool_node extends.  */
+  cgraph_node *func;
+  FOR_EACH_FUNCTION (func)
+{
+  dw_die_ref die = lookup_decl_die (func->decl);
+  if (die == NULL)
+   continue;
+
+  ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, die);
+  if (dtd == NULL)
+   continue;
+
+  /* Functions actually get two types: a BTF_KIND_FUNC_PROTO, and
+also a BTF_KIND_FUNC.  But the CTF container only allocates one
+type per function, which matches closely with BTF_KIND_FUNC_PROTO.
+For each such function, also allocate a BTF_KIND_FUNC entry.
+These will be output later.  */
+  ctf_dtdef_ref func_dtd = ggc_cleared_alloc ();
+  func_dtd->dtd_data = dtd->dtd_data;
+  func_dtd->dtd_data.ctti_type = dtd->dtd_type;
+  func_dtd->linkage = dtd->linkage;
+  func_dtd->dtd_type = num_types_added + num_types_created;
+
+  /* Only the BTF_KIND_FUNC type actually references the name. The
+BTF_KIND_FUNC_PROTO is always anonymous.  */
+  dtd->dtd_data.ctti_name = 0;
+
+  vec_safe_push (funcs, func_dtd);
+  num_types_created++;
+
+  /* Mark any 'extern' funcs and add DATASEC entries for them.  */
+  if (DECL_EXTERNAL (func->decl))
+   {
+ func_dtd->linkage = BTF_FUNC_EXTERN;
+
+ const char *section_name = get_section_name (func);
+ /* Note: get_section_name () returns NULL for functions in text
+section.  This is intentional, since we do not want to generate
+DATASEC entries for them.  */
+ if (section_name == NULL)
+   continue;
+
+ struct btf_var_secinfo info;
+
+ /* +1 for the sentinel type not in the types map.  */
+ info.type = func_dtd->dtd_type + 1;
+
+ /* Both zero at compile time.  */
+ info.size = 0;
+ info.offset = 0;
+
+ btf_datasec_push_entry (ctfc, section_name, info);
+   }
+}
+
   varpool_node *node;
   FOR_EACH_VARIABLE (node)
 {
@@ -313,28 +394,13 @@ btf_collect_datasec (ctf_container_ref ctfc)
   if (dvd == NULL)
continue;
 
-  const char *section_name = node->get_section ();
   /* Mark extern variables.  */

[PATCH v2 2/3] btf: fix 'extern const void' variables [PR106773]

2022-12-13 Thread David Faust via Gcc-patches
[Changes from v1: Minor updates to comments per review. ]

The eBPF loader expects to find BTF_KIND_VAR records for references to
extern const void symbols. We were mistakenly identifing these as
unsupported types, and as a result skipping emitting VAR records for
them.

In addition, the internal DWARF representation from which BTF is
produced does not generate 'const' modifier DIEs for the void type,
which meant in BTF the 'const' qualifier was dropped for 'extern const
void' variables. This patch also adds support for generating a const
void type in BTF to correct emission for these variables.

PR target/106773

gcc/

* btfout.cc (btf_collect_datasec): Correct size of void entries.
(btf_dvd_emit_preprocess_cb): Do not skip emitting variables which
refer to void types.
(btf_init_postprocess): Create 'const void' type record if needed and
adjust variables to refer to it as appropriate.

gcc/testsuite/

* gcc.dg/debug/btf/btf-pr106773.c: New test.
---
 gcc/btfout.cc | 44 +--
 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c | 25 +++
 2 files changed, 65 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 677e8324424..204b11d4e9f 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -350,6 +350,8 @@ btf_collect_datasec (ctf_container_ref ctfc)
   tree size = DECL_SIZE_UNIT (node->decl);
   if (tree_fits_uhwi_p (size))
info.size = tree_to_uhwi (size);
+  else if (VOID_TYPE_P (TREE_TYPE (node->decl)))
+   info.size = 1;
 
   /* Offset is left as 0 at compile time, to be filled in by loaders such
 as libbpf.  */
@@ -441,7 +443,7 @@ btf_dvd_emit_preprocess_cb (ctf_dvdef_ref *slot, 
ctf_container_ref arg_ctfc)
 return 1;
 
   /* Do not add variables which refer to unsupported types.  */
-  if (btf_removed_type_p (var->dvd_type))
+  if (!voids.contains (var->dvd_type) && btf_removed_type_p (var->dvd_type))
 return 1;
 
   arg_ctfc->ctfc_vars_list[num_vars_added] = var;
@@ -1075,15 +1077,49 @@ btf_init_postprocess (void)
 {
   ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
 
-  size_t i;
-  size_t num_ctf_types = tu_ctfc->ctfc_types->elements ();
-
   holes.create (0);
   voids.create (0);
 
   num_types_added = 0;
   num_types_created = 0;
 
+  /* Workaround for 'const void' variables.  These variables are sometimes used
+ in eBPF programs to address kernel symbols.  DWARF does not generate const
+ qualifier on void type, so we would incorrectly emit these variables
+ without the const qualifier.
+ Unfortunately we need the TREE node to know it was const, and we need
+ to create the const modifier type (if needed) now, before making the types
+ list.  So we can't avoid iterating with FOR_EACH_VARIABLE here, and then
+ again when creating the DATASEC entries.  */
+  ctf_id_t constvoid_id = CTF_NULL_TYPEID;
+  varpool_node *var;
+  FOR_EACH_VARIABLE (var)
+{
+  if (!var->decl)
+   continue;
+
+  tree type = TREE_TYPE (var->decl);
+  if (type && VOID_TYPE_P (type) && TYPE_READONLY (type))
+   {
+ dw_die_ref die = lookup_decl_die (var->decl);
+ if (die == NULL)
+   continue;
+
+ ctf_dvdef_ref dvd = ctf_dvd_lookup (tu_ctfc, die);
+ if (dvd == NULL)
+   continue;
+
+ /* Create the 'const' modifier type for void.  */
+ if (constvoid_id == CTF_NULL_TYPEID)
+   constvoid_id = ctf_add_reftype (tu_ctfc, CTF_ADD_ROOT,
+   dvd->dvd_type, CTF_K_CONST, NULL);
+ dvd->dvd_type = constvoid_id;
+   }
+}
+
+  size_t i;
+  size_t num_ctf_types = tu_ctfc->ctfc_types->elements ();
+
   if (num_ctf_types)
 {
   init_btf_id_map (num_ctf_types + 1);
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
new file mode 100644
index 000..f90fa773a4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
@@ -0,0 +1,25 @@
+/* Test BTF generation for extern const void symbols.
+   BTF_KIND_VAR records should be emitted for such symbols if they are used,
+   as well as a corresponding entry in the appropriate DATASEC record.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* Expect 1 variable record only for foo, with 'extern' (2) linkage.  */
+/* { dg-final { scan-assembler-times "\[\t \]0xe00\[\t 
\]+\[^\n\]*btv_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*btv_linkage" 1 
} } */
+
+/* { dg-final { scan-assembler-times "ascii \"foo.0\"\[\t 
\]+\[^\n\]*btf_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0\[\t \]+\[^\n\]*bts_offset" 1 } } */
+/* { dg-final { scan-assembler-times "1\[\t \]+\[^\n\]*bts_size" 1 } } */
+
+extern const void foo __attribute__((weak)) __attribute__((secti

[PATCH v2 1/3] btf: add 'extern' linkage for variables [PR106773]

2022-12-13 Thread David Faust via Gcc-patches
[Changes from v1:
 - Add enum btf_var_linkage in include/btf.h and use that instead of
   local #defines.
 - Fix BTF generation for extern variable with both non-defining and
   defining decls in the same CU. Add a test for this. ]

Add support for the 'extern' linkage value for BTF_KIND_VAR records,
which is used for variables declared as extern in the source file.

This also fixes a bug with BTF generation for extern variables which
have both a non-defining declaration and a defining declaration in the
same CU.

PR target/106773

gcc/

* btfout.cc (btf_collect_datasec): Mark extern variables as such.
(btf_dvd_emit_preprocess_cb): Skip non-defining extern variable decl
if there is a defining decl for the same variable.
(btf_asm_varent): Accomodate 'extern' linkage.

gcc/testsuite/

* gcc.dg/debug/btf/btf-variables-4.c: New test.
* gcc.dg/debug/btf/btf-variables-5.c: New test.

include/

* btf.h (enum btf_var_linkage): New.
(struct btf_var): Update comment to note 'extern' linkage.
---
 gcc/btfout.cc | 11 -
 .../gcc.dg/debug/btf/btf-variables-4.c| 24 +++
 .../gcc.dg/debug/btf/btf-variables-5.c| 19 +++
 include/btf.h | 11 -
 4 files changed, 63 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-variables-5.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index aef9fd70a28..677e8324424 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -314,6 +314,9 @@ btf_collect_datasec (ctf_container_ref ctfc)
continue;
 
   const char *section_name = node->get_section ();
+  /* Mark extern variables.  */
+  if (DECL_EXTERNAL (node->decl))
+   dvd->dvd_visibility = BTF_VAR_GLOBAL_EXTERN;
 
   if (section_name == NULL)
{
@@ -431,6 +434,12 @@ btf_dvd_emit_preprocess_cb (ctf_dvdef_ref *slot, 
ctf_container_ref arg_ctfc)
 {
   ctf_dvdef_ref var = (ctf_dvdef_ref) * slot;
 
+  /* If this is an extern variable declaration with a defining declaration
+ later, skip it so that only the defining declaration is emitted.
+ This is the same case, fix and reasoning as in CTF; see PR105089.  */
+  if (ctf_dvd_ignore_lookup (arg_ctfc, var->dvd_key))
+return 1;
+
   /* Do not add variables which refer to unsupported types.  */
   if (btf_removed_type_p (var->dvd_type))
 return 1;
@@ -676,7 +685,7 @@ btf_asm_varent (ctf_dvdef_ref var)
   dw2_asm_output_data (4, var->dvd_name_offset, "btv_name");
   dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_VAR, 0, 0), "btv_info");
   dw2_asm_output_data (4, get_btf_id (var->dvd_type), "btv_type");
-  dw2_asm_output_data (4, (var->dvd_visibility ? 1 : 0), "btv_linkage");
+  dw2_asm_output_data (4, var->dvd_visibility, "btv_linkage");
 }
 
 /* Asm'out a member description following a BTF_KIND_STRUCT or
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c
new file mode 100644
index 000..d77600bae1c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c
@@ -0,0 +1,24 @@
+/* Test BTF generation for extern variables.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* Expect 4 variables.  */
+/* { dg-final { scan-assembler-times "\[\t \]0xe00\[\t 
\]+\[^\n\]*btv_info" 4 } } */
+
+/* 2 extern, 1 global, 1 static.  */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*btv_linkage" 1 } 
} */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*btv_linkage" 1 
} } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*btv_linkage" 2 
} } */
+
+extern int a;
+extern const int b;
+int c;
+static const int d = 5;
+
+int foo (int x)
+{
+  c = a + b + x;
+
+  return c + d;
+}
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-variables-5.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-5.c
new file mode 100644
index 000..8aae76cacab
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-5.c
@@ -0,0 +1,19 @@
+/* Test BTF generation for extern variable with both non-defining and
+   defining declarations.
+
+   In this case, only a single variable record should be emitted,
+   with 'global' linkage. However two array types will be generated.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* Expect 1 variable with global (1) linkage.  */
+/* { dg-final { scan-assembler-times "\[\t \]0xe00\[\t 
\]+\[^\n\]*btv_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*btv_linkage" 1 
} } */
+
+/* Expect 2 array types, one of which is unsized.  */
+/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t \]+\[^\n\]*bta_nelems" 1 
} } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*bta_nelems" 1 } 
} */
+
+extern const char FOO[];
+const char FOO[] = "foo";
di

[PATCH v2 0/3] btf: fix BTF for extern items [PR106773]

2022-12-13 Thread David Faust via Gcc-patches
[Changes from v1:
 - Remove #defines for LINKAGE_* values, instead mirror enums from
   linux/btf.h to include/btf.h and use those.
 - Fix BTF generation for extern variable with both non-defining and
   defining decls in the same CU. Add a test for this.
 - Update several comments per review feedback. ]

Hi,

This series fixes the issues reported in target/PR106773. I decided to
split it into three commits, as there are ultimately three distinct
issues and fixes. See each patch for details.

Tested on bpf-unknown-none and x86_64-linux-gnu, no known regressions.

OK to push?
Thanks.

David Faust (3):
  btf: add 'extern' linkage for variables [PR106773]
  btf: fix 'extern const void' variables [PR106773]
  btf: correct generation for extern funcs [PR106773]

 gcc/btfout.cc | 184 +-
 .../gcc.dg/debug/btf/btf-datasec-2.c  |  28 +++
 .../gcc.dg/debug/btf/btf-function-6.c |  19 ++
 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c |  25 +++
 .../gcc.dg/debug/btf/btf-variables-4.c|  24 +++
 .../gcc.dg/debug/btf/btf-variables-5.c|  19 ++
 include/btf.h |  29 ++-
 7 files changed, 276 insertions(+), 52 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-datasec-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-function-6.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-variables-5.c

-- 
2.38.1



Re: [PATCH 2/3] btf: fix 'extern const void' variables [PR106773]

2022-12-12 Thread David Faust via Gcc-patches



On 12/8/22 23:34, Indu Bhagat wrote:
> Looks OK to me overall. Minor comments below.
> 
> Thanks
> 
> On 12/7/22 12:57, David Faust wrote:
>> The eBPF loader expects to find BTF_KIND_VAR records for references to
>> extern const void symbols. We were mistakenly identifing these as
>> unsupported types, and as a result skipping emitting VAR records for
>> them.
>>
>> In addition, the internal DWARF representation from which BTF is
>> produced does not generate 'const' modifier DIEs for the void type,
>> which meant in BTF the 'const' qualifier was dropped for 'extern const
>> void' variables. This patch also adds support for generating a const
>> void type in BTF to correct emission for these variables.
>>
>>  PR target/106773
>>
>> gcc/
>>
>>  * btfout.cc (btf_collect_datasec): Correct size of void entries.
>>  (btf_dvd_emit_preprocess_cb): Do not skip emitting variables which
>>  refer to void types.
>>  (btf_init_postprocess): Create 'const void' type record if needed and
>>  adjust variables to refer to it as appropriate.
>>
>> gcc/testsuite/
>>
>>  * gcc.dg/debug/btf/btf-pr106773.c: New test.
>> ---
>>   gcc/btfout.cc | 44 +--
>>   gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c | 25 +++
>>   2 files changed, 65 insertions(+), 4 deletions(-)
>>   create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
>>
>> diff --git a/gcc/btfout.cc b/gcc/btfout.cc
>> index a1c6266a7db..05f3a3f9b6e 100644
>> --- a/gcc/btfout.cc
>> +++ b/gcc/btfout.cc
>> @@ -354,6 +354,8 @@ btf_collect_datasec (ctf_container_ref ctfc)
>> tree size = DECL_SIZE_UNIT (node->decl);
>> if (tree_fits_uhwi_p (size))
>>  info.size = tree_to_uhwi (size);
>> +  else if (VOID_TYPE_P (TREE_TYPE (node->decl)))
>> +info.size = 1;
>>   
>> /* Offset is left as 0 at compile time, to be filled in by loaders 
>> such
>>   as libbpf.  */
>> @@ -439,7 +441,7 @@ btf_dvd_emit_preprocess_cb (ctf_dvdef_ref *slot, 
>> ctf_container_ref arg_ctfc)
>> ctf_dvdef_ref var = (ctf_dvdef_ref) * slot;
>>   
>> /* Do not add variables which refer to unsupported types.  */
>> -  if (btf_removed_type_p (var->dvd_type))
>> +  if (!voids.contains (var->dvd_type) && btf_removed_type_p (var->dvd_type))
>>   return 1;
>>   
>> arg_ctfc->ctfc_vars_list[num_vars_added] = var;
>> @@ -1073,15 +1075,49 @@ btf_init_postprocess (void)
>>   {
>> ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
>>   
>> -  size_t i;
>> -  size_t num_ctf_types = tu_ctfc->ctfc_types->elements ();
>> -
>> holes.create (0);
>> voids.create (0);
>>   
>> num_types_added = 0;
>> num_types_created = 0;
>>   
>> +  /* Workaround for 'const void' variables. These variables are sometimes 
>> used
>> + in eBPF programs to address kernel symbols. DWARF does not generate 
>> const
>> + qualifier on void type, so we would incorrectly emit these variables
>> + without the const qualifier.
>> + Unfortunately we need the TREE node to know it was const, and we need
>> + to create the const modifier type (if needed) now, before making the 
>> types
>> + list. So we can't avoid iterating with FOR_EACH_VARIABLE here, and then
>> + again when creating the DATASEC entries.  */
> 
> "Dot, space, space, new sentence." in 3 places.
> 
> 
>> +  ctf_id_t constvoid_id = CTF_NULL_TYPEID;
>> +  varpool_node *var;
>> +  FOR_EACH_VARIABLE (var)
>> +{
>> +  if (!var->decl)
>> +continue;
>> +
>> +  tree type = TREE_TYPE (var->decl);
>> +  if (type && VOID_TYPE_P (type) && TYPE_READONLY (type))
>> +{
>> +  dw_die_ref die = lookup_decl_die (var->decl);
>> +  if (die == NULL)
>> +continue;
>> +
>> +  ctf_dvdef_ref dvd = ctf_dvd_lookup (tu_ctfc, die);
>> +  if (dvd == NULL)
>> +continue;
>> +
>> +  /* Create the 'const' modifier type for void.  */
>> +  if (constvoid_id == CTF_NULL_TYPEID)
>> +constvoid_id = ctf_add_reftype (tu_ctfc, CTF_ADD_ROOT,
>> +dvd->dvd_type, CTF_K_CONST, NULL);
> 
> No de-duplication of the const void type.  I assume libbpf will take 
> care of this eventually.

Hm, not sure I follow. Where is the duplication? The const void type is
only created once here, for the first such variable which needs it, and
reused for subsequent variables. And it does not already exist in the
CTF which we are translating into BTF.

In any case, yes libbpf can handle duplicated types. Though it would
still be good to minimize that where we can to not bloat the BTF info.

> 
>> +  dvd->dvd_type = constvoid_id;
>> +}
>> +}
>> +
>> +  size_t i;
>> +  size_t num_ctf_types = tu_ctfc->ctfc_types->elements ();
>> +
>> if (num_ctf_types)
>>   {
>> init_btf_id_map (num_ctf_types + 1);
>> diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c 
>> b/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
>> new file mode 100

Re: [PATCH 1/3] btf: add 'extern' linkage for variables [PR106773]

2022-12-12 Thread David Faust via Gcc-patches



On 12/8/22 22:55, Indu Bhagat wrote:
> Hi David,
> 
> On 12/7/22 12:57, David Faust wrote:
>> Add support for the 'extern' linkage value for BTF_KIND_VAR records,
>> which is used for variables declared as extern in the source file.
>>
>>  PR target/106773
>>
>> gcc/
>>
>>  * btfout.cc (BTF_LINKAGE_STATIC): New define.
>>  (BTF_LINKAGE_GLOBAL): Likewise.
>>  (BTF_LINKAGE_EXTERN): Likewise.
>>  (btf_collect_datasec): Mark extern variables as such.
>>  (btf_asm_varent): Accomodate 'extern' linkage.
>>
>> gcc/testsuite/
>>
>>  * gcc.dg/debug/btf/btf-variables-4.c: New test.
>>
>> include/
>>
>>  * btf.h (struct btf_var): Update comment to note 'extern' linkage.
>> ---
>>   gcc/btfout.cc |  9 ++-
>>   .../gcc.dg/debug/btf/btf-variables-4.c| 24 +++
>>   include/btf.h |  2 +-
>>   3 files changed, 33 insertions(+), 2 deletions(-)
>>   create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c
>>
>> diff --git a/gcc/btfout.cc b/gcc/btfout.cc
>> index aef9fd70a28..a1c6266a7db 100644
>> --- a/gcc/btfout.cc
>> +++ b/gcc/btfout.cc
>> @@ -66,6 +66,10 @@ static char btf_info_section_label[MAX_BTF_LABEL_BYTES];
>>   
>>   #define BTF_INVALID_TYPEID 0x
>>   
>> +#define BTF_LINKAGE_STATIC 0
>> +#define BTF_LINKAGE_GLOBAL 1
>> +#define BTF_LINKAGE_EXTERN 2
>> +
> 
> I was about to suggest to rename these to use the same name as used in 
> the kernel btf.h. What is used there is:
>  BTF_VAR_STATIC = 0,
>  BTF_VAR_GLOBAL_ALLOCATED = 1,
>  BTF_VAR_GLOBAL_EXTERN = 2,
> 
> But after looking at the Patch 3/3, I see you reuse these definitions 
> for functions as well. I just find the names confusing on the first look 
> - "BTF_LINKAGE_STATIC".
> 
> Naming aside, what do you think about adding the defines to 
> include/btf.h instead ?

Actually, I forgot these are defined (separately for both VARs and FUNCs)
in the kernel uapi/linux/btf.h. It would probably be best to mirror that
approach and use a separate enum for each, in include/btf.h. WDYT?

> 
>>   /* Mapping of CTF variables to the IDs they will be assigned when they are
>>  converted to BTF_KIND_VAR type records. Strictly accounts for the index
>>  from the start of the variable type entries, does not include the number
>> @@ -314,6 +318,9 @@ btf_collect_datasec (ctf_container_ref ctfc)
>>  continue;
>>   
>> const char *section_name = node->get_section ();
>> +  /* Mark extern variables.  */
>> +  if (DECL_EXTERNAL (node->decl))
>> +dvd->dvd_visibility = BTF_LINKAGE_EXTERN;
>>   
> 
> This made me think about the following case.
> 
> extern const char a[];
> const char a[] = "foo";
> 
> What is the expected BTF for this? Since BTF can differentiate between 
> the non-defining extern variable declaration, I expected to see two 
> variables with different "linkage". At this time I see, two variables 
> with global linkage but different types:
> 
>  .long   0xe00   # btv_info
>  .long   0x4 # btv_type
>  .long   0x1 # btv_linkage
>  .long   0x1f# btv_name
>  .long   0xe00   # btv_info
>  .long   0x7 # btv_type
>  .long   0x1 # btv_linkage
>  .long   0x60# btt_name
> 

The BTF documentation in the kernel does not clarify this case.
Going off the implementation in clang as a reference, it looks like
only one VAR record is expected, with 'global' linkage:

$ cat extdef.c
extern const char a[];
const char a[] = "foo";

$ clang -target bpf -c -g extdef.c -o extdef.o

$ /usr/sbin/bpftool btf dump file extdef.o   
[1] CONST '(anon)' type_id=2
[2] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
[3] ARRAY '(anon)' type_id=1 index_type_id=4 nr_elems=4
[4] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
[5] VAR 'a' type_id=3, linkage=global
[6] DATASEC '.rodata' size=0 vlen=1
type_id=5 offset=0 size=4 (VAR 'a')

In GCC we have two records since we have two DIEs for "a" in the
DWARF. One has type "const char[4]" and the other has type
"const char[]", so the BTF records point to two different types
as well.

I guess we should find a way in BTF to identify this and
emit only the defining definition as clang does.


>> if (section_name == NULL)
>>  {
>> @@ -676,7 +683,7 @@ btf_asm_varent (ctf_dvdef_ref var)
>> dw2_asm_output_data (4, var->dvd_name_offset, "btv_name");
>> dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_VAR, 0, 0), "btv_info");
>> dw2_asm_output_data (4, get_btf_id (var->dvd_type), "btv_type");
>> -  dw2_asm_output_data (4, (var->dvd_visibility ? 1 : 0), "btv_linkage");
>> +  dw2_asm_output_data (4, var->dvd_visibility, "btv_linkage");
>>   }
>>   
>>   /* Asm'out a member description following a BTF_KIND_STRUCT or
>> diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-variabl

Re: [PATCH 3/3] btf: correct generation for extern funcs [PR106773]

2022-12-12 Thread David Faust via Gcc-patches



On 12/8/22 23:36, Indu Bhagat wrote:
> On 12/7/22 12:57, David Faust wrote:
>> The eBPF loader expects to find entries for functions declared as extern
>> in the corresponding BTF_KIND_DATASEC record, but we were not generating
>> these entries.
>>
>> This patch adds support for the 'extern' linkage of function types in
>> BTF, and creates entries for for them BTF_KIND_DATASEC records as needed.
>>
>>  PR target/106773
>>
>> gcc/
>>
>>  * btfout.cc (get_section_name): New function.
>>  (btf_collect_datasec): Use it here. Process functions, marking them
>>  'extern' and generating DATASEC entries for them as appropriate. Move
>>  creation of BTF_KIND_FUNC records to here...
>>  (btf_dtd_emit_preprocess_cb): ... from here.
>>
>> gcc/testsuite/
>>
>>  * gcc.dg/debug/btf/btf-datasec-2.c: New test.
>>  * gcc.dg/debug/btf/btf-function-6.c: New test.
>>
>> include/
>>
>>  * btf.h (struct btf_var_secinfo): Update comments with notes about
>>  extern functions.
>> ---
>>   gcc/btfout.cc | 129 --
>>   .../gcc.dg/debug/btf/btf-datasec-2.c  |  28 
>>   .../gcc.dg/debug/btf/btf-function-6.c |  19 +++
>>   include/btf.h |   9 +-
>>   4 files changed, 139 insertions(+), 46 deletions(-)
>>   create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-datasec-2.c
>>   create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-function-6.c
>>
>> diff --git a/gcc/btfout.cc b/gcc/btfout.cc
>> index 05f3a3f9b6e..d7ead377ec5 100644
>> --- a/gcc/btfout.cc
>> +++ b/gcc/btfout.cc
>> @@ -294,7 +294,35 @@ btf_datasec_push_entry (ctf_container_ref ctfc, const 
>> char *secname,
>> ds.entries.safe_push (info);
>>   
>> datasecs.safe_push (ds);
>> -  num_types_created++;
>> +}
>> +
>> +
>> +/* Return the section name, as of interest to btf_collect_datasec, for the
>> +   given symtab node. Note that this deliberately returns NULL for objects
>> +   which do not go in a section btf_collect_datasec cares about.  */
> 
> "Dot, space, space, new sentence."
> 
>> +static const char *
>> +get_section_name (symtab_node *node)
>> +{
>> +  const char *section_name = node->get_section ();
>> +
>> +  if (section_name == NULL)
>> +{
>> +  switch (categorize_decl_for_section (node->decl, 0))
>> +{
>> +case SECCAT_BSS:
>> +  section_name = ".bss";
>> +  break;
>> +case SECCAT_DATA:
>> +  section_name = ".data";
>> +  break;
>> +case SECCAT_RODATA:
>> +  section_name = ".rodata";
>> +  break;
>> +default:;
>> +}
>> +}
>> +
>> +  return section_name;
>>   }
>>   
>>   /* Construct all BTF_KIND_DATASEC records for CTFC. One such record is 
>> created
>> @@ -305,7 +333,60 @@ btf_datasec_push_entry (ctf_container_ref ctfc, const 
>> char *secname,
>>   static void
>>   btf_collect_datasec (ctf_container_ref ctfc)
>>   {
>> -  /* See cgraph.h struct symtab_node, which varpool_node extends.  */
>> +  cgraph_node *func;
>> +  FOR_EACH_FUNCTION (func)
>> +{
>> +  dw_die_ref die = lookup_decl_die (func->decl);
>> +  if (die == NULL)
>> +continue;
>> +
>> +  ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, die);
>> +  if (dtd == NULL)
>> +continue;
>> +
>> +  /* Functions actually get two types: a BTF_KIND_FUNC_PROTO, and
>> + also a BTF_KIND_FUNC. But the CTF container only allocates one
>> + type per function, which matches closely with BTF_KIND_FUNC_PROTO.
>> + For each such function, also allocate a BTF_KIND_FUNC entry.
>> + These will be output later.  */
> 
> "Dot, space, space, new sentence."
> 
>> +  ctf_dtdef_ref func_dtd = ggc_cleared_alloc ();
>> +  func_dtd->dtd_data = dtd->dtd_data;
>> +  func_dtd->dtd_data.ctti_type = dtd->dtd_type;
>> +  func_dtd->linkage = dtd->linkage;
>> +  func_dtd->dtd_type = num_types_added + num_types_created;
>> +
>> +  /* Only the BTF_KIND_FUNC type actually references the name. The
>> + BTF_KIND_FUNC_PROTO is always anonymous.  */
>> +  dtd->dtd_data.ctti_name = 0;
>> +
>> +  vec_safe_push (funcs, func_dtd);
>> +  num_types_created++;
>> +
>> +  /* Mark any 'extern' funcs and add DATASEC entries for them.  */
>> +  if (DECL_EXTERNAL (func->decl))
>> +{
>> +  func_dtd->linkage = BTF_LINKAGE_EXTERN;
>> +
> 
> What is the expected BTF when both decl and definition are present:
> 
> extern int extfunc(int x);
> int extfunc (int x) {
>int y = foo ();
>return y;
> }

Using clang implementation as the reference, a single FUNC record
for "extfunc" with "global" linkage:

$ cat extfuncdef.c 
extern int extfunc (int x);
int extfunc (int x) {
  int y = foo ();
  return y;
}

$ clang -target bpf -c -g extfuncdef.c -o extfuncdef.o

$ /usr/sbin/bpftool btf dump file extfuncdef.o
[1] FUNC_PROTO '(anon)' ret_type_id=2 vlen=1
'(anon)' type_id=2
[2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[3] FUNC 'extfu

[PATCH] bpf: add define_insn for bswap

2022-12-08 Thread David Faust via Gcc-patches
The eBPF architecture provides 'end[be,le]' instructions for endianness
swapping. Add a define_insn for bswap2 to use them instaed of
falling back on a libcall.

Tested on bpf-unknown-none, no known regressions.

OK to commit?
Thanks

gcc/

* config/bpf/bpf.md (bswap2): New define_insn.

gcc/testsuite/

* gcc.target/bpf/bswap-1.c: New test.
---
 gcc/config/bpf/bpf.md  | 17 +
 gcc/testsuite/gcc.target/bpf/bswap-1.c | 23 +++
 2 files changed, 40 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/bpf/bswap-1.c

diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index a28021aef26..22a133f1c79 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -341,6 +341,23 @@ (define_insn "lshr3"
   "rsh\t%0,%2"
   [(set_attr "type" "")])
 
+ Endianness conversion
+
+(define_mode_iterator BSM [HI SI DI])
+(define_mode_attr endmode [(HI "16") (SI "32") (DI "64")])
+
+(define_insn "bswap2"
+  [(set (match_operand:BSM 0 "register_operand""=r")
+(bswap:BSM (match_operand:BSM 1 "register_operand" " r")))]
+  ""
+{
+  if (TARGET_BIG_ENDIAN)
+return "endle\t%0, ";
+  else
+return "endbe\t%0, ";
+}
+  [(set_attr "type" "end")])
+
  Conditional branches
 
 ;; The eBPF jump instructions use 64-bit arithmetic when evaluating
diff --git a/gcc/testsuite/gcc.target/bpf/bswap-1.c 
b/gcc/testsuite/gcc.target/bpf/bswap-1.c
new file mode 100644
index 000..4748143ada5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/bswap-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-mlittle-endian" } */
+
+unsigned short in16 = 0x1234U;
+unsigned int   in32 = 0x12345678U;
+unsigned long  in64 = 0x123456789abcdef0ULL;
+
+unsigned short out16 = 0;
+unsigned int   out32 = 0;
+unsigned long  out64 = 0;
+
+int foo (void)
+{
+  out16 = __builtin_bswap16 (in16);
+  out32 = __builtin_bswap32 (in32);
+  out64 = __builtin_bswap64 (in64);
+
+  return 0;
+}
+
+/* { dg-final { scan-assembler "endbe\t%r., 16" } } */
+/* { dg-final { scan-assembler "endbe\t%r., 32" } } */
+/* { dg-final { scan-assembler "endbe\t%r., 64" } } */
-- 
2.38.1



[PATCH 1/3] btf: add 'extern' linkage for variables [PR106773]

2022-12-07 Thread David Faust via Gcc-patches
Add support for the 'extern' linkage value for BTF_KIND_VAR records,
which is used for variables declared as extern in the source file.

PR target/106773

gcc/

* btfout.cc (BTF_LINKAGE_STATIC): New define.
(BTF_LINKAGE_GLOBAL): Likewise.
(BTF_LINKAGE_EXTERN): Likewise.
(btf_collect_datasec): Mark extern variables as such.
(btf_asm_varent): Accomodate 'extern' linkage.

gcc/testsuite/

* gcc.dg/debug/btf/btf-variables-4.c: New test.

include/

* btf.h (struct btf_var): Update comment to note 'extern' linkage.
---
 gcc/btfout.cc |  9 ++-
 .../gcc.dg/debug/btf/btf-variables-4.c| 24 +++
 include/btf.h |  2 +-
 3 files changed, 33 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index aef9fd70a28..a1c6266a7db 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -66,6 +66,10 @@ static char btf_info_section_label[MAX_BTF_LABEL_BYTES];
 
 #define BTF_INVALID_TYPEID 0x
 
+#define BTF_LINKAGE_STATIC 0
+#define BTF_LINKAGE_GLOBAL 1
+#define BTF_LINKAGE_EXTERN 2
+
 /* Mapping of CTF variables to the IDs they will be assigned when they are
converted to BTF_KIND_VAR type records. Strictly accounts for the index
from the start of the variable type entries, does not include the number
@@ -314,6 +318,9 @@ btf_collect_datasec (ctf_container_ref ctfc)
continue;
 
   const char *section_name = node->get_section ();
+  /* Mark extern variables.  */
+  if (DECL_EXTERNAL (node->decl))
+   dvd->dvd_visibility = BTF_LINKAGE_EXTERN;
 
   if (section_name == NULL)
{
@@ -676,7 +683,7 @@ btf_asm_varent (ctf_dvdef_ref var)
   dw2_asm_output_data (4, var->dvd_name_offset, "btv_name");
   dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_VAR, 0, 0), "btv_info");
   dw2_asm_output_data (4, get_btf_id (var->dvd_type), "btv_type");
-  dw2_asm_output_data (4, (var->dvd_visibility ? 1 : 0), "btv_linkage");
+  dw2_asm_output_data (4, var->dvd_visibility, "btv_linkage");
 }
 
 /* Asm'out a member description following a BTF_KIND_STRUCT or
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c
new file mode 100644
index 000..d77600bae1c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c
@@ -0,0 +1,24 @@
+/* Test BTF generation for extern variables.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* Expect 4 variables.  */
+/* { dg-final { scan-assembler-times "\[\t \]0xe00\[\t 
\]+\[^\n\]*btv_info" 4 } } */
+
+/* 2 extern, 1 global, 1 static.  */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*btv_linkage" 1 } 
} */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*btv_linkage" 1 
} } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*btv_linkage" 2 
} } */
+
+extern int a;
+extern const int b;
+int c;
+static const int d = 5;
+
+int foo (int x)
+{
+  c = a + b + x;
+
+  return c + d;
+}
diff --git a/include/btf.h b/include/btf.h
index eba67f9d599..9a757ce5bc9 100644
--- a/include/btf.h
+++ b/include/btf.h
@@ -182,7 +182,7 @@ struct btf_param
information about the variable.  */
 struct btf_var
 {
-  uint32_t linkage;/* Currently only 0=static or 1=global.  */
+  uint32_t linkage;/* 0=static, 1=global, 2=extern.  */
 };
 
 /* BTF_KIND_DATASEC is followed by VLEN struct btf_var_secinfo entries,
-- 
2.38.1



[PATCH 3/3] btf: correct generation for extern funcs [PR106773]

2022-12-07 Thread David Faust via Gcc-patches
The eBPF loader expects to find entries for functions declared as extern
in the corresponding BTF_KIND_DATASEC record, but we were not generating
these entries.

This patch adds support for the 'extern' linkage of function types in
BTF, and creates entries for for them BTF_KIND_DATASEC records as needed.

PR target/106773

gcc/

* btfout.cc (get_section_name): New function.
(btf_collect_datasec): Use it here. Process functions, marking them
'extern' and generating DATASEC entries for them as appropriate. Move
creation of BTF_KIND_FUNC records to here...
(btf_dtd_emit_preprocess_cb): ... from here.

gcc/testsuite/

* gcc.dg/debug/btf/btf-datasec-2.c: New test.
* gcc.dg/debug/btf/btf-function-6.c: New test.

include/

* btf.h (struct btf_var_secinfo): Update comments with notes about
extern functions.
---
 gcc/btfout.cc | 129 --
 .../gcc.dg/debug/btf/btf-datasec-2.c  |  28 
 .../gcc.dg/debug/btf/btf-function-6.c |  19 +++
 include/btf.h |   9 +-
 4 files changed, 139 insertions(+), 46 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-datasec-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-function-6.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 05f3a3f9b6e..d7ead377ec5 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -294,7 +294,35 @@ btf_datasec_push_entry (ctf_container_ref ctfc, const char 
*secname,
   ds.entries.safe_push (info);
 
   datasecs.safe_push (ds);
-  num_types_created++;
+}
+
+
+/* Return the section name, as of interest to btf_collect_datasec, for the
+   given symtab node. Note that this deliberately returns NULL for objects
+   which do not go in a section btf_collect_datasec cares about.  */
+static const char *
+get_section_name (symtab_node *node)
+{
+  const char *section_name = node->get_section ();
+
+  if (section_name == NULL)
+{
+  switch (categorize_decl_for_section (node->decl, 0))
+   {
+   case SECCAT_BSS:
+ section_name = ".bss";
+ break;
+   case SECCAT_DATA:
+ section_name = ".data";
+ break;
+   case SECCAT_RODATA:
+ section_name = ".rodata";
+ break;
+   default:;
+   }
+}
+
+  return section_name;
 }
 
 /* Construct all BTF_KIND_DATASEC records for CTFC. One such record is created
@@ -305,7 +333,60 @@ btf_datasec_push_entry (ctf_container_ref ctfc, const char 
*secname,
 static void
 btf_collect_datasec (ctf_container_ref ctfc)
 {
-  /* See cgraph.h struct symtab_node, which varpool_node extends.  */
+  cgraph_node *func;
+  FOR_EACH_FUNCTION (func)
+{
+  dw_die_ref die = lookup_decl_die (func->decl);
+  if (die == NULL)
+   continue;
+
+  ctf_dtdef_ref dtd = ctf_dtd_lookup (ctfc, die);
+  if (dtd == NULL)
+   continue;
+
+  /* Functions actually get two types: a BTF_KIND_FUNC_PROTO, and
+also a BTF_KIND_FUNC. But the CTF container only allocates one
+type per function, which matches closely with BTF_KIND_FUNC_PROTO.
+For each such function, also allocate a BTF_KIND_FUNC entry.
+These will be output later.  */
+  ctf_dtdef_ref func_dtd = ggc_cleared_alloc ();
+  func_dtd->dtd_data = dtd->dtd_data;
+  func_dtd->dtd_data.ctti_type = dtd->dtd_type;
+  func_dtd->linkage = dtd->linkage;
+  func_dtd->dtd_type = num_types_added + num_types_created;
+
+  /* Only the BTF_KIND_FUNC type actually references the name. The
+BTF_KIND_FUNC_PROTO is always anonymous.  */
+  dtd->dtd_data.ctti_name = 0;
+
+  vec_safe_push (funcs, func_dtd);
+  num_types_created++;
+
+  /* Mark any 'extern' funcs and add DATASEC entries for them.  */
+  if (DECL_EXTERNAL (func->decl))
+   {
+ func_dtd->linkage = BTF_LINKAGE_EXTERN;
+
+ const char *section_name = get_section_name (func);
+ /* Note: get_section_name () returns NULL for functions in text
+section. This is intentional, since we do not want to generate
+DATASEC entries for them.  */
+ if (section_name == NULL)
+   continue;
+
+ struct btf_var_secinfo info;
+
+ /* +1 for the sentinel type not in the types map.  */
+ info.type = func_dtd->dtd_type + 1;
+
+ /* Both zero at compile time.  */
+ info.size = 0;
+ info.offset = 0;
+
+ btf_datasec_push_entry (ctfc, section_name, info);
+   }
+}
+
   varpool_node *node;
   FOR_EACH_VARIABLE (node)
 {
@@ -317,28 +398,13 @@ btf_collect_datasec (ctf_container_ref ctfc)
   if (dvd == NULL)
continue;
 
-  const char *section_name = node->get_section ();
   /* Mark extern variables.  */
   if (DECL_EXTERNAL (node->decl))
dvd->dvd_visibility = BTF_LINKAGE_EXTERN;
 
+  const char *section_name = get_section_name (node);
   if (se

[PATCH 2/3] btf: fix 'extern const void' variables [PR106773]

2022-12-07 Thread David Faust via Gcc-patches
The eBPF loader expects to find BTF_KIND_VAR records for references to
extern const void symbols. We were mistakenly identifing these as
unsupported types, and as a result skipping emitting VAR records for
them.

In addition, the internal DWARF representation from which BTF is
produced does not generate 'const' modifier DIEs for the void type,
which meant in BTF the 'const' qualifier was dropped for 'extern const
void' variables. This patch also adds support for generating a const
void type in BTF to correct emission for these variables.

PR target/106773

gcc/

* btfout.cc (btf_collect_datasec): Correct size of void entries.
(btf_dvd_emit_preprocess_cb): Do not skip emitting variables which
refer to void types.
(btf_init_postprocess): Create 'const void' type record if needed and
adjust variables to refer to it as appropriate.

gcc/testsuite/

* gcc.dg/debug/btf/btf-pr106773.c: New test.
---
 gcc/btfout.cc | 44 +--
 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c | 25 +++
 2 files changed, 65 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index a1c6266a7db..05f3a3f9b6e 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -354,6 +354,8 @@ btf_collect_datasec (ctf_container_ref ctfc)
   tree size = DECL_SIZE_UNIT (node->decl);
   if (tree_fits_uhwi_p (size))
info.size = tree_to_uhwi (size);
+  else if (VOID_TYPE_P (TREE_TYPE (node->decl)))
+   info.size = 1;
 
   /* Offset is left as 0 at compile time, to be filled in by loaders such
 as libbpf.  */
@@ -439,7 +441,7 @@ btf_dvd_emit_preprocess_cb (ctf_dvdef_ref *slot, 
ctf_container_ref arg_ctfc)
   ctf_dvdef_ref var = (ctf_dvdef_ref) * slot;
 
   /* Do not add variables which refer to unsupported types.  */
-  if (btf_removed_type_p (var->dvd_type))
+  if (!voids.contains (var->dvd_type) && btf_removed_type_p (var->dvd_type))
 return 1;
 
   arg_ctfc->ctfc_vars_list[num_vars_added] = var;
@@ -1073,15 +1075,49 @@ btf_init_postprocess (void)
 {
   ctf_container_ref tu_ctfc = ctf_get_tu_ctfc ();
 
-  size_t i;
-  size_t num_ctf_types = tu_ctfc->ctfc_types->elements ();
-
   holes.create (0);
   voids.create (0);
 
   num_types_added = 0;
   num_types_created = 0;
 
+  /* Workaround for 'const void' variables. These variables are sometimes used
+ in eBPF programs to address kernel symbols. DWARF does not generate const
+ qualifier on void type, so we would incorrectly emit these variables
+ without the const qualifier.
+ Unfortunately we need the TREE node to know it was const, and we need
+ to create the const modifier type (if needed) now, before making the types
+ list. So we can't avoid iterating with FOR_EACH_VARIABLE here, and then
+ again when creating the DATASEC entries.  */
+  ctf_id_t constvoid_id = CTF_NULL_TYPEID;
+  varpool_node *var;
+  FOR_EACH_VARIABLE (var)
+{
+  if (!var->decl)
+   continue;
+
+  tree type = TREE_TYPE (var->decl);
+  if (type && VOID_TYPE_P (type) && TYPE_READONLY (type))
+   {
+ dw_die_ref die = lookup_decl_die (var->decl);
+ if (die == NULL)
+   continue;
+
+ ctf_dvdef_ref dvd = ctf_dvd_lookup (tu_ctfc, die);
+ if (dvd == NULL)
+   continue;
+
+ /* Create the 'const' modifier type for void.  */
+ if (constvoid_id == CTF_NULL_TYPEID)
+   constvoid_id = ctf_add_reftype (tu_ctfc, CTF_ADD_ROOT,
+   dvd->dvd_type, CTF_K_CONST, NULL);
+ dvd->dvd_type = constvoid_id;
+   }
+}
+
+  size_t i;
+  size_t num_ctf_types = tu_ctfc->ctfc_types->elements ();
+
   if (num_ctf_types)
 {
   init_btf_id_map (num_ctf_types + 1);
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
new file mode 100644
index 000..f90fa773a4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
@@ -0,0 +1,25 @@
+/* Test BTF generation for extern const void symbols.
+   BTF_KIND_VAR records should be emitted for such symbols if they are used,
+   as well as a corresponding entry in the appropriate DATASEC record.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* Expect 1 variable record only for foo, with 'extern' (2) linkage.  */
+/* { dg-final { scan-assembler-times "\[\t \]0xe00\[\t 
\]+\[^\n\]*btv_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t \]+\[^\n\]*btv_linkage" 1 
} } */
+
+/* { dg-final { scan-assembler-times "ascii \"foo.0\"\[\t 
\]+\[^\n\]*btf_string" 1 } } */
+
+/* { dg-final { scan-assembler-times "0\[\t \]+\[^\n\]*bts_offset" 1 } } */
+/* { dg-final { scan-assembler-times "1\[\t \]+\[^\n\]*bts_size" 1 } } */
+
+extern const void foo __attribute__((weak)) __attribute__((section 
(".ksyms")));
+extern cons

[PATCH 0/3] btf: fix BTF for extern items [PR106773]

2022-12-07 Thread David Faust via Gcc-patches
Hi,

This series fixes the issues reported in target/PR106773. I decided to
split it into three commits, as there are ultimately three distinct
issues and fixes. See each patch for details.

Tested on bpf-unknown-none and x86_64-linux-gnu, no known regressions.

OK to push?
Thanks.

David Faust (3):
  btf: add 'extern' linkage for variables [PR106773]
  btf: fix 'extern const void' variables [PR106773]
  btf: correct generation for extern funcs [PR106773]

 gcc/btfout.cc | 182 +-
 .../gcc.dg/debug/btf/btf-datasec-2.c  |  28 +++
 .../gcc.dg/debug/btf/btf-function-6.c |  19 ++
 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c |  25 +++
 .../gcc.dg/debug/btf/btf-variables-4.c|  24 +++
 include/btf.h |  11 +-
 6 files changed, 237 insertions(+), 52 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-datasec-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-function-6.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-variables-4.c

-- 
2.38.1



[committed] bpf: avoid possible use of uninitialized variable

2022-11-15 Thread David Faust via Gcc-patches
Fix a maybe-uninitialized warning introduced in commit:
068baae1864 bpf: add preserve_field_info builtin

Thanks to Jan-Benedict Glaw for pointing this out.

Tested on bpf-unknown-none, committed as obvious.

gcc/

* config/bpf/bpf.cc (bpf_expand_builtin): Avoid use of uninitialized
variable in error case.
---
 gcc/config/bpf/bpf.cc | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 16af2412bf6..51e46955015 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -1254,11 +1254,14 @@ bpf_expand_builtin (tree exp, rtx target 
ATTRIBUTE_UNUSED,
   /* A resolved overloaded __builtin_preserve_field_info.  */
   tree src = CALL_EXPR_ARG (exp, 0);
   tree kind_tree = CALL_EXPR_ARG (exp, 1);
-  unsigned HOST_WIDE_INT kind_val;
+  unsigned HOST_WIDE_INT kind_val = 0;
   if (tree_fits_uhwi_p (kind_tree))
kind_val = tree_to_uhwi (kind_tree);
   else
-   error ("invalid argument to built-in function");
+   {
+ error ("invalid argument to built-in function");
+ return expand_normal (error_mark_node);
+   }
 
   enum btf_core_reloc_kind kind = (enum btf_core_reloc_kind) kind_val;
 
-- 
2.37.2



[PATCH] bpf: Use enum for resolved overloaded builtins

2022-11-07 Thread David Faust via Gcc-patches
Change several places in the eBPF backend dealing with overloaded
built-in functions to consistently use the enum bpf_builtins type,
rather than variously using integer constants or booleans. The result is
eaiser to read and extend.

Tested on bpf-unknown-none, no known regressions.
OK to push?

Thanks.

gcc/

* config/bpf/bpf.cc (struct core_walk_data): Add field `which'...
(bpf_resolve_overloaded_builtin): ... set it here. Use values of enum
bpf_builtins for error checks.
(bpf_core_walk): Use values of enum bpf_builtins.
(bpf_core_newdecl): Likewise.
(bpf_expand_builtin): Likewise.
---
 gcc/config/bpf/bpf.cc | 106 +++---
 1 file changed, 59 insertions(+), 47 deletions(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index fd4003c2bfc..16af2412bf6 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -1222,7 +1222,7 @@ bpf_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
   return gen_rtx_REG (ops[0].mode, BPF_R0);
 }
 
-  else if (code == -1)
+  else if (code == -BPF_BUILTIN_PRESERVE_ACCESS_INDEX)
 {
   /* A resolved overloaded __builtin_preserve_access_index.  */
   tree arg = CALL_EXPR_ARG (exp, 0);
@@ -1249,7 +1249,7 @@ bpf_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
   return expand_normal (arg);
 }
 
-  else if (code == -2)
+  else if (code == -BPF_BUILTIN_PRESERVE_FIELD_INFO)
 {
   /* A resolved overloaded __builtin_preserve_field_info.  */
   tree src = CALL_EXPR_ARG (exp, 0);
@@ -1444,28 +1444,37 @@ bpf_core_get_index (const tree node)
__builtin_preserve_access_index.  */
 
 static tree
-bpf_core_newdecl (tree type, bool is_pai)
+bpf_core_newdecl (tree type, enum bpf_builtins which)
 {
   tree rettype;
   char name[80];
   static unsigned long pai_count = 0;
   static unsigned long pfi_count = 0;
 
-  if (is_pai)
+  switch (which)
 {
-  rettype = build_function_type_list (type, type, NULL);
-  int len = snprintf (name, sizeof (name), "%s", "__builtin_pai_");
-  len = snprintf (name + len, sizeof (name) - len, "%lu", pai_count++);
-}
-  else
-{
-  rettype = build_function_type_list (unsigned_type_node, type,
- unsigned_type_node, NULL);
-  int len = snprintf (name, sizeof (name), "%s", "__builtin_pfi_");
-  len = snprintf (name + len, sizeof (name) - len, "%lu", pfi_count++);
+case BPF_BUILTIN_PRESERVE_ACCESS_INDEX:
+  {
+   rettype = build_function_type_list (type, type, NULL);
+   int len = snprintf (name, sizeof (name), "%s", "__builtin_pai_");
+   len = snprintf (name + len, sizeof (name) - len, "%lu", pai_count++);
+  }
+  break;
+
+case BPF_BUILTIN_PRESERVE_FIELD_INFO:
+  {
+   rettype = build_function_type_list (unsigned_type_node, type,
+   unsigned_type_node, NULL);
+   int len = snprintf (name, sizeof (name), "%s", "__builtin_pfi_");
+   len = snprintf (name + len, sizeof (name) - len, "%lu", pfi_count++);
+  }
+  break;
+
+default:
+  gcc_unreachable ();
 }
 
-  return add_builtin_function_ext_scope (name, rettype, is_pai ? -1 : -2,
+  return add_builtin_function_ext_scope (name, rettype, -which,
 BUILT_IN_MD, NULL, NULL_TREE);
 }
 
@@ -1492,6 +1501,7 @@ bpf_core_is_maybe_aggregate_access (tree expr)
 
 struct core_walk_data {
   location_t loc;
+  enum bpf_builtins which;
   tree arg;
 };
 
@@ -1501,7 +1511,6 @@ static tree
 bpf_core_walk (tree *tp, int *walk_subtrees, void *data)
 {
   struct core_walk_data *dat = (struct core_walk_data *) data;
-  bool is_pai = dat->arg == NULL_TREE;
 
   /* If this is a type, don't do anything. */
   if (TYPE_P (*tp))
@@ -1510,19 +1519,21 @@ bpf_core_walk (tree *tp, int *walk_subtrees, void *data)
   return NULL_TREE;
 }
 
-  /* Build a new function call to a resolved builtin for the desired operation.
- If this is a preserve_field_info call, pass along the argument to the
- resolved builtin call. */
-  if (bpf_core_is_maybe_aggregate_access (*tp))
-{
-  tree newdecl = bpf_core_newdecl (TREE_TYPE (*tp), is_pai);
-  tree newcall;
-  if (is_pai)
-   newcall = build_call_expr_loc (dat->loc, newdecl, 1, *tp);
-  else
-   newcall = build_call_expr_loc (dat->loc, newdecl, 2, *tp, dat->arg);
+  /* Build a new function call to a type-resolved temporary builtin for the
+ desired operation, and pass along args as necessary.  */
+  tree newdecl = bpf_core_newdecl (TREE_TYPE (*tp), dat->which);
 
-  *tp = newcall;
+  if (dat->which == BPF_BUILTIN_PRESERVE_ACCESS_INDEX)
+{
+  if (bpf_core_is_maybe_aggregate_access (*tp))
+   {
+ *tp = build_call_expr_loc (dat->loc, newdecl, 1, *tp);
+ *walk_subtrees = 0;
+   }
+}
+  else
+{
+  *tp = build_call_expr_loc (dat->loc, newdecl, 2, *tp, 

[committed] bpf: cleanup missed refactor

2022-11-07 Thread David Faust via Gcc-patches
Commit 068baae1864 "bpf: add preserve_field_info builtin" factored out
some repeated code to a new function maybe_make_core_relo (), but missed
using it in one place. Clean that up.

Regtested on bpf-unknown-none, pushed as obvious.

gcc/

* config/bpf/bpf.cc (handle_attr_preserve): Use maybe_make_core_relo().
---
 gcc/config/bpf/bpf.cc | 24 +---
 1 file changed, 1 insertion(+), 23 deletions(-)

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index ea8ca64d1d6..fd4003c2bfc 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -1731,7 +1731,6 @@ handle_attr_preserve (function *fn)
 {
   basic_block bb;
   rtx_insn *insn;
-  rtx_code_label *label;
   FOR_EACH_BB_FN (bb, fn)
 {
   FOR_BB_INSNS (bb, insn)
@@ -1762,28 +1761,7 @@ handle_attr_preserve (function *fn)
}
 
  if (is_attr_preserve_access (expr))
-   {
- auto_vec accessors;
- tree container = bpf_core_compute (expr, &accessors);
- if (accessors.length () < 1)
-   continue;
- accessors.reverse ();
-
- container = TREE_TYPE (container);
- const char * section_name;
- if (DECL_SECTION_NAME (fn->decl))
-   section_name = DECL_SECTION_NAME (fn->decl);
- else
-   section_name = ".text";
-
- label = gen_label_rtx ();
- LABEL_PRESERVE_P (label) = 1;
- emit_label (label);
-
- /* Add the CO-RE relocation information to the BTF 
container.  */
- bpf_core_reloc_add (container, section_name, &accessors, 
label,
- BPF_RELO_FIELD_BYTE_OFFSET);
-   }
+   maybe_make_core_relo (expr, BPF_RELO_FIELD_BYTE_OFFSET);
}
}
  rtx_insn *seq = get_insns ();
-- 
2.37.2



Re: [PATCH v3] bpf: add preserve_field_info builtin

2022-10-26 Thread David Faust via Gcc-patches


On 10/26/22 12:33, Jose E. Marchesi wrote:
> 
> Hi David.
> 
> Thanks for the updates.
> OK for master.
> 

Pushed, thanks.


[PATCH v3] bpf: add preserve_field_info builtin

2022-10-26 Thread David Faust via Gcc-patches
>> I'm not sure whether this behavior is a known limitation or an
>> oversight. In my opinion it makes more sense to error at compile time,
>> becuase even after the loader patches the return value it still will
>> not be correct for these cases.
>>
>> So for now I've set these cases to error out, but it would be just as
>> simple to mimic the LLVM behavior. WDYT?
> 
> I would say it makes more sense to error out than to return invalid
> data.
> 
> However, the divergence wrt LLVM is a concern.  What about keeping this
> behavior in the GCC backend and simultaneously raise the issue in
> bpf@vger?  If it was a design oversight and the change doesn't impact
> kernel sources, they may be willing to change it.
> 

OK, I will raise the question there.

>> [...]
>> +@deftypefn {Built-in Function} unsigned int __builtin_preserve_field_info 
>> (@var{expr}, unsigned int @var{kind})
>> +BPF Compile Once-Run Everywhere (CO-RE) support. This builtin is used to
>> +extract information to aid in struct/union relocations.  @var{expr} is
>> +an access to a field of a struct or union. Depending on @var{kind}, 
>> different
>> +information is returned to the program. A CO-RE relocation for the access in
>> +@var{expr} with kind @var{kind} is recorded if @code{-mco-re} is in effect.
>> +
>> +The following values are supported for @var{kind}:
>> +@table @var
>> +@item FIELD_BYTE_OFFSET = 0
>> +The returned value is the offset, in bytes, of the field from the
>> +beginning of the containing structure.
> 
> What about bit fields?  Is this the byte offset of the containing word?

Yes.

> 
>> +@item FIELD_BYTE_SIZE = 1
>> +The returned value is the size, in bytes, of the field.
> 
> For bit fields,  is this the size of the containing word?

Right again. I have updated the docs for these two in v3.

> 
>> +@item FIELD_EXISTENCE = 2
>> +The returned value is 1 if the field exists, 0 otherwise. Always 1 at
>> +compile time.
>> +
>> +@item FIELD_SIGNEDNESS = 3
>> +The returned value is 1 if the field is signed, 0 otherwise.
>> +
>> +@item FIELD_LSHIFT_U64 = 4
>> +@itemx FIELD_RSHIFT_U64 = 5
>> +Suppose the field were loaded into a value of FIELD_BYTE_SIZE bytes
>> +and then zero or sign-extended to a 64-bit value. The returned value
>> +is the number of bits of left or right shifting respectively that
>> +would be needed to recover the original value of the field.
> 
> What are the semantics for bit fields?

The semantics for bit fields are the same. These two are primarily
useful for bit fields - a common case in eBPF programs is to read
some field of a struct through a pointer. If it's a kernel struct
that may change between versions and you are reading a bit field,
you would use this builtin to get the eBPF loader to patch the
appropriate steps to extract the field.

So the process to read a bit field is the following:

  1. read FIELD_BYTE_SIZE bytes and zero-extend the value of the
 read into a u64
  2. left shift the result FIELD_LSHIFT_U64 bits
  3. if FIELD_SIGNEDNESS
   then arithmetic right-shift by FIELD_RSHIFT_U64 bits
 otherwise
   logical right-shift by FIELD_RSHIFT_U64 bits

Where all these FIELD_* values might change between kernels and
need patching by the eBPF loader.

I struggled a bit trying to find the best wording to describe this
in the docs, and settled on adding some example code since I think
that is the most clear.

Please take a look at the updated version and let me know if you
have any suggestions, I'm happy to hear them.

Thanks

---

[Changes from v2: update documentation in extend.texi]

Add BPF __builtin_preserve_field_info. This builtin is used to extract
information to facilitate struct and union relocations performed by the
BPF loader, especially for bitfields.

The builtin has the following signature:

  unsigned int __builtin_preserve_field_info (EXPR, unsigned int KIND);

Where EXPR is an expression accessing a field of a struct or union.
Depending on KIND, different information is returned to the program. The
supported values for KIND are as follows:

  enum {
FIELD_BYTE_OFFSET = 0,
FIELD_BYTE_SIZE,
FIELD_EXISTENCE,
FIELD_SIGNEDNESS,
FIELD_LSHIFT_U64,
FIELD_RSHIFT_U64
  };

If -mco-re is in effect (explicitly or implicitly specified), a CO-RE
relocation is added for the access in EXPR recording the relevant
information according to KIND.

gcc/

* config/bpf/bpf.cc: Support __builtin_preserve_field_info.
(enum bpf_builtins): Add new builtin.
(bpf_init_builtins): Likewise.
(bpf_core_field_info): New function.
(bpf_expand_builtin): Accomodate new builtin. Refactor adding new
relocation to...
(maybe_make_core_relo): ... here. New function.
(bpf_resolve_overloaded_builtin): Accomodate new builtin.
(bpf_core_newdecl): Likewise.
(bpf_core_walk): Likewise.
(bpf_core_is_maybe_aggregate_access): Improve logic.
(struct core_walk_data): New.
* config/bpf/coreout

[PATCH v2] bpf: add preserve_field_info builtin

2022-10-25 Thread David Faust via Gcc-patches
Hi Jose,

Thanks for your comments. I think I've addressed them all in the updated
patch below.

>>+  get_inner_reference (src, &bitsize, &bitpos, &var_off, &mode, &unsignedp,
>>+&reversep, &volatilep);
>
>Since the information returned by the builtin is always constant
>(positions, sizes) I think you will want to adjust the code for the
>eventuality of variable positioned fields and also variable sized
>fields.
>
>get_inner_reference sets var_off to a tree if the position of the field
>is variable.  In these cases `bitpos' is relative to that position.
>
>Likewise, get_inner_reference sets `mode' is set to BLKmode and
>`bitsize' will be set to -1.
>
>I'm not sure what the built-in is supposed to do/return in these cases.
>I guess it makes sense to error out, but what does LLVM do?

I would have thought erroring out the only option, but it seems that
LLVM will return a value from the builtin and record a CO-RE relocation
as normal.

What value will be returned depends of course on KIND, but from what
I can tell it seems that such fields are treated as having an offset of
0 bits and/or a size of 0 bits. For example FIELD_BYTE_SIZE for a
flexible-length array will return 0. FIELD_RSHIFT_U64 will be
calculated as 64 - 0 = 64.

This sort of makes sense if you expect that any BPF loader will honor
the CO-RE relocations and patch the return value before the program is
run, i.e. the actual values at compile time are irrelevant.

But, I'm not sure that BPF loaders in practice actually _can_ patch the
return value correctly. The source of information for resolving the
relocations is the BTF. But the BTF won't have more information about
variable position/size members. A flexible-length array for example in
BTF is represented as an array type with 0 elements. So the size
calculation when patching the relocation (looking at the impl in
libbpf) will be elem_size * nelems = 0, and the 'patched' values will
be the same as the unpatched.

I'm not sure whether this behavior is a known limitation or an
oversight. In my opinion it makes more sense to error at compile time,
becuase even after the loader patches the return value it still will
not be correct for these cases.

So for now I've set these cases to error out, but it would be just as
simple to mimic the LLVM behavior. WDYT?


>If I read this properly, for something like:
>
>__builtin_preserve_field_info (a = foo.bar + bar.baz, KIND)
>
>On one side CO-RE relocations are computed for both foo.bar and bar.baz
>(I see bpf_core_compute does that) as expected.
>
>But then the builtin returns information that can only apply to one
>access.  Which one?

Expressions like this should not be accepted by the builtin. I didn't
consider this case in v1 so it led to an ICE. Clang rejects this
outright and errors with "argument 1 is not a field access". It is
actually very strict about the expressions that are accepted, unlike
__builtin_preserve_access_index.

I have updated this implementation to behave more like clang in that
it will reject any expression that isn't directly a field access. That
even includes rejecting things like:

  __builtin_preserve_field_info (&foo.bar, KIND)

Since unlike preserve_access_index this builtin does not actually
perform the operation in EXPR, it makes sense to enforce that EXPR must
be exactly a single field access.

---

[Changes from v1:
  - Error gracefully on variable-size or variable-offset fields if the
requested information according to KIND cannot be calculated for
an access to such a field, instead of maybe computing garbage.
  - Check for invalid expressions in EXPR and reject them rather than
ICEing later. This includes rejecting some expressions which were
accepted by previous patch but not by clang/LLVM.
  - Improve precision of location information for errors.
  - Add function-level comment describing maybe_make_core_relo ().
  - Document return values for all supported values of KIND.
  - Add tests for error conditions. ]

Add BPF __builtin_preserve_field_info. This builtin is used to extract
information to facilitate struct and union relocations performed by the
BPF loader, especially for bitfields.

The builtin has the following signature:

  unsigned int __builtin_preserve_field_info (EXPR, unsigned int KIND);

Where EXPR is an expression accessing a field of a struct or union.
Depending on KIND, different information is returned to the program. The
supported values for KIND are as follows:

  enum {
FIELD_BYTE_OFFSET = 0,
FIELD_BYTE_SIZE,
FIELD_EXISTENCE,
FIELD_SIGNEDNESS,
FIELD_LSHIFT_U64,
FIELD_RSHIFT_U64
  };

If -mco-re is in effect (explicitly or implicitly specified), a CO-RE
relocation is added for the access in EXPR recording the relevant
information according to KIND.

gcc/

* config/bpf/bpf.cc: Support __builtin_preserve_field_info.
(enum bpf_builtins): Add new builtin.
(bpf_init_builtins): Likewise.
(bpf_core_field_info): New

[PATCH] bpf: add preserve_field_info builtin

2022-10-19 Thread David Faust via Gcc-patches
Add BPF __builtin_preserve_field_info. This builtin is used to extract
information to facilitate struct and union relocations performed by the
BPF loader, especially for bitfields.

The builtin has the following signature:

  unsigned int __builtin_preserve_field_info (EXPR, unsigned int KIND);

Where EXPR is an expression accessing a field of a struct or union.
Depending on KIND, different information is returned to the program. The
supported values for KIND are as follows:

  enum {
FIELD_BYTE_OFFSET = 0,
FIELD_BYTE_SIZE,
FIELD_EXISTENCE,
FIELD_SIGNEDNESS,
FIELD_LSHIFT_U64,
FIELD_RSHIFT_U64
  };

If -mco-re is in effect (explicitly or implicitly specified), a CO-RE
relocation is added for the access in EXPR recording the relevant
information according to KIND.

Tested on bpf-unknown-none, no known regressions.
OK?

Thanks

gcc/

* config/bpf/bpf.cc: Support __builtin_preserve_field_info.
(enum bpf_builtins): Add new builtin.
(bpf_init_builtins): Likewise.
(bpf_core_field_info): New function.
(bpf_expand_builtin): Accomodate new builtin. Refactor adding new
relocation to...
(maybe_make_core_relo): ... here. New function.
(bpf_resolve_overloaded_builtin): Accomodate new builtin.
(bpf_core_newdecl): Likewise.
(bpf_core_walk): Likewise.
(bpf_core_is_maybe_aggregate_access): Improve logic.
(struct core_walk_data): New.
* config/bpf/coreout.cc (bpf_core_reloc_add): Allow adding different
relocation kinds.
* config/bpf/coreout.h: Analogous change.
* doc/extend.texi: Document BPF __builtin_preserve_field_info.

gcc/testsuite/

* gcc.target/bpf/core-builtin-fieldinfo-existence-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-offset-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-sign-1.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-sign-2.c: New test.
* gcc.target/bpf/core-builtin-fieldinfo-size-1.c: New test.
---
 gcc/config/bpf/bpf.cc | 327 ++
 gcc/config/bpf/coreout.cc |   5 +-
 gcc/config/bpf/coreout.h  |   2 +-
 gcc/doc/extend.texi   |  21 ++
 .../bpf/core-builtin-fieldinfo-existence-1.c  |  34 ++
 .../bpf/core-builtin-fieldinfo-lshift-1-be.c  |  37 ++
 .../bpf/core-builtin-fieldinfo-lshift-1-le.c  |  37 ++
 .../bpf/core-builtin-fieldinfo-lshift-2.c |  37 ++
 .../bpf/core-builtin-fieldinfo-offset-1.c |  56 +++
 .../bpf/core-builtin-fieldinfo-rshift-1.c |  36 ++
 .../bpf/core-builtin-fieldinfo-rshift-2.c |  35 ++
 .../bpf/core-builtin-fieldinfo-sign-1.c   |  33 ++
 .../bpf/core-builtin-fieldinfo-sign-2.c   |  45 +++
 .../bpf/core-builtin-fieldinfo-size-1.c   |  43 +++
 14 files changed, 676 insertions(+), 72 deletions(-)
 create mode 100644 
gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-existence-1.c
 create mode 100644 
gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-be.c
 create mode 100644 
gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-1-le.c
 create mode 100644 
gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-lshift-2.c
 create mode 100644 
gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-offset-1.c
 create mode 100644 
gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-1.c
 create mode 100644 
gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-rshift-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-1.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-sign-2.c
 create mode 100644 gcc/testsuite/gcc.target/bpf/core-builtin-fieldinfo-size-1.c

diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index 51055651707..41a506349b2 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -184,13 +184,13 @@ enum bpf_builtins
 
   /* Compile Once - Run Everywhere (CO-RE) support.  */
   BPF_BUILTIN_PRESERVE_ACCESS_INDEX,
+  BPF_BUILTIN_PRESERVE_FIELD_INFO,
 
   BPF_BUILTIN_MAX,
 };
 
 static GTY (()) tree bpf_builtins[(int) BPF_BUILTIN_MAX];
 
-
 void bpf_register_coreattr_pass (void);
 
 /* Initialize the per-function machine status.  */
@@ -966,6 +966,9 @@ bpf_init_builtins (void)
   def_builtin ("__builtin_preserve_access_index",
   BPF_BUILTIN_PRESERVE_ACCESS_INDEX,
   build_function_type_list (ptr_type_node, ptr_type_node, 0));
+  def_builtin ("__builtin_preserve_field_info",
+  BPF_BUILTIN_PRESERVE_FIELD_INFO,
+  build_function_type_list (unsigned_type_node, ptr

Re: [PATCH] btf: Add support to BTF_KIND_ENUM64 type

2022-09-28 Thread David Faust via Gcc-patches
Hi Guillermo,

Thanks for the patch. Just a couple of small nits on the changelog
entries below but otherwise very nice, LGTM.

But, please wait a couple of days before pushing to give Indu time
to raise any objections about the changes in ctfc/dwarf2ctf.

Thanks!
David

On 8/29/22 14:11, Guillermo E. Martinez via Gcc-patches wrote:
> Hello GCC team,
> 
> The following patch update BTF/CTF backend to support
> BTF_KIND_ENUM64 type.
> 
> Comments will be welcomed and appreciated!,
> 
> Kind regards,
> guillermo
> --
> 
> BTF supports 64-bits enumerators with following encoding:
> 
>   struct btf_type:
> name_off: 0 or offset to a valid C identifier
> info.kind_flag: 0 for unsigned, 1 for signed
> info.kind: BTF_KIND_ENUM64
> info.vlen: number of enum values
> size: 1/2/4/8
> 
> The btf_type is followed by info.vlen number of:
> 
> struct btf_enum64
> {
>   uint32_t name_off;   /* Offset in string section of enumerator name.  */
>   uint32_t val_lo32;   /* lower 32-bit value for a 64-bit value 
> Enumerator */
>   uint32_t val_hi32;   /* high 32-bit value for a 64-bit value Enumerator 
> */
> };
> 
> So, a new btf_enum64 structure was added to represent BTF_KIND_ENUM64
> and a new field in ctf_dtdef to represent specific type's properties, in
> the particular case for CTF enums it helps to distinguish when its
> enumerators values are signed or unsigned, later that information is
> used to encode the BTF enum type.
> 
> gcc/ChangeLog:
> 
>   * btfout.cc (btf_calc_num_vbytes): Compute enumeration size depending of
>   enumerator type btf_enum{,64}.
>   (btf_asm_type): Update btf_kflag according to enumerators sign,
>   using correct BPF type in BTF_KIND_ENUMi{,64}.
>   (btf_asm_enum_const): New argument to represent the size of
>   the BTF enum type.
>   * ctfc.cc (ctf_add_enum): Use and initialization of flag field to
>   CTF_ENUM_F_NONE.
>   (ctf_add_enumerator): New argument to represent CTF flags,
>   updating the comment and flag vaue according to enumerators
>   sing.
>   * ctfc.h (ctf_dmdef): Update dmd_value to HOST_WIDE_INT to allow
>   use 32/64 bits enumerators.
>   (ctf_dtdef): Add flags to to describe specifyc type's properties.

typo: specific

>   * dwarf2ctf.cc (gen_ctf_enumeration_type): Update flags field
>   depending when a signed enumerator value is found.
>   include/btf.h (btf_enum64): Add new definition and new symbolic
>   constant to BTF_KIND_ENUM64 and BTF_KF_ENUM_{UN,}SIGNED.

Missing an * here for include/btf.h

> 
> gcc/testsuite/ChangeLog:
> 
>   gcc.dg/debug/btf/btf-enum-1.c: Update testcase, with correct
>   info.kflags encoding.
>   gcc.dg/debug/btf/btf-enum64-1.c: New testcase.

Likewise for these ChangeLog entries.

You can use contrib/gcc-changelog/git_check_commit.py to check the
formatting of the entries.

> ---
>  gcc/btfout.cc | 24 ---
>  gcc/ctfc.cc   | 14 ---
>  gcc/ctfc.h|  9 +++-
>  gcc/dwarf2ctf.cc  |  9 +++-
>  gcc/testsuite/gcc.dg/debug/btf/btf-enum-1.c   |  2 +-
>  gcc/testsuite/gcc.dg/debug/btf/btf-enum64-1.c | 41 +++
>  include/btf.h | 19 +++--
>  7 files changed, 99 insertions(+), 19 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-enum64-1.c
> 
> diff --git a/gcc/btfout.cc b/gcc/btfout.cc
> index 997a33fa089..4b11c867c23 100644
> --- a/gcc/btfout.cc
> +++ b/gcc/btfout.cc
> @@ -223,7 +223,9 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
>break;
>  
>  case BTF_KIND_ENUM:
> -  vlen_bytes += vlen * sizeof (struct btf_enum);
> +  vlen_bytes += (dtd->dtd_data.ctti_size == 0x8)
> + ? vlen * sizeof (struct btf_enum64)
> + : vlen * sizeof (struct btf_enum);
>break;
>  
>  case BTF_KIND_FUNC_PROTO:
> @@ -622,6 +624,15 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
>btf_size_type = 0;
>  }
>  
> + if (btf_kind == BTF_KIND_ENUM)
> +   {
> + btf_kflag = (dtd->flags & CTF_ENUM_F_ENUMERATORS_SIGNED)
> + ? BTF_KF_ENUM_SIGNED
> + : BTF_KF_ENUM_UNSIGNED;
> + if (dtd->dtd_data.ctti_size == 0x8)
> +   btf_kind = BTF_KIND_ENUM64;
> +   }
> +
>dw2_asm_output_data (4, dtd->dtd_data.ctti_name, "btt_name");
>dw2_asm_output_data (4, BTF_TYPE_INFO (btf_kind, btf_kflag, btf_vlen),
>  "btt_info: kind=%u, kflag=%u, vlen=%u",
> @@ -634,6 +645,7 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
>  case BTF_KIND_UNION:
>  case BTF_KIND_ENUM:
>  case BTF_KIND_DATASEC:
> +case BTF_KIND_ENUM64:
>dw2_asm_output_data (4, dtd->dtd_data.ctti_size, "btt_size: %uB",
>  dtd->dtd_data.ctti_size);
>return;
> @@ -707,13 +719,13 @@ btf_asm_s

[PATCH] btf: do not skip emitting void variables [PR106773]

2022-09-01 Thread David Faust via Gcc-patches
The eBPF loader expects to find BTF_KIND_VAR records for references to
extern const void symbols. We were mistakenly identifing these as
unsupported types, and as a result skipping emitting VAR records for
them.

Tested on bpf-unknown-none and x86_64, no known regressions.
OK?

Thanks.

gcc/ChangeLog:

PR target/106773
* btfout.cc (btf_dvd_emit_preprocess_cb): Do not skip emitting
variables which refer to void types.

gcc/testsuite/ChangeLog:

PR target/106773
* gcc.dg/debug/btf/btf-pr106773.c: New test.
---
 gcc/btfout.cc |  2 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c | 21 +++
 2 files changed, 22 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 997a33fa089..37ec662c190 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -430,7 +430,7 @@ btf_dvd_emit_preprocess_cb (ctf_dvdef_ref *slot, 
ctf_container_ref arg_ctfc)
   ctf_dvdef_ref var = (ctf_dvdef_ref) * slot;
 
   /* Do not add variables which refer to unsupported types.  */
-  if (btf_removed_type_p (var->dvd_type))
+  if (!voids.contains (var->dvd_type) && btf_removed_type_p (var->dvd_type))
 return 1;
 
   arg_ctfc->ctfc_vars_list[num_vars_added] = var;
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
new file mode 100644
index 000..4de15f76546
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-pr106773.c
@@ -0,0 +1,21 @@
+/* Test BTF generation for extern const void symbols.
+   BTF_KIND_VAR records should be emitted for such symbols if they are used.  
*/
+
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* Expect 1 variable record only for foo.  */
+/* { dg-final { scan-assembler-times "\[\t \]0xe00\[\t 
\]+\[^\n\]*btv_info" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t \]+\[^\n\]*btv_linkage" 1 
} } */
+
+/* { dg-final { scan-assembler-times "ascii \"foo.0\"\[\t 
\]+\[^\n\]*btf_string" 1 } } */
+
+extern const void foo;
+extern const void bar;
+
+unsigned long func () {
+  unsigned long x = (unsigned long) &foo;
+
+  return x;
+}
+
-- 
2.36.1



[PATCH v2] bpf: handle anonymous members in CO-RE reloc [PR106745]

2022-08-29 Thread David Faust via Gcc-patches
[changes from v1: simplify the new conditional logic as suggested.]

The old method for computing a member index for a CO-RE relocation
relied on a name comparison, which could SEGV if the member in question
is itself part of an anonymous inner struct or union.

This patch changes the index computation to not rely on a name, while
maintaining the ability to account for other sibling fields which may
not have a representation in BTF.

Tested in bpf-unknown-none, no known regressions.
OK?

Thanks.

gcc/ChangeLog:

PR target/106745
* config/bpf/coreout.cc (bpf_core_get_sou_member_index): Fix
computation of index for anonymous members.

gcc/testsuite/ChangeLog:

PR target/106745
* gcc.target/bpf/core-pr106745.c: New test.
---
 gcc/config/bpf/coreout.cc| 16 +++
 gcc/testsuite/gcc.target/bpf/core-pr106745.c | 30 
 2 files changed, 40 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/core-pr106745.c

diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
index cceaaa969cc..8897a045ea1 100644
--- a/gcc/config/bpf/coreout.cc
+++ b/gcc/config/bpf/coreout.cc
@@ -207,7 +207,6 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, 
const tree node)
   if (TREE_CODE (node) == FIELD_DECL)
 {
   const tree container = DECL_CONTEXT (node);
-  const char * name = IDENTIFIER_POINTER (DECL_NAME (node));
 
   /* Lookup the CTF type info for the containing type.  */
   dw_die_ref die = lookup_type_die (container);
@@ -222,16 +221,21 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, 
const tree node)
   if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
 return -1;
 
+  tree field = TYPE_FIELDS (container);
   int i = 0;
   ctf_dmdef_t * dmd;
   for (dmd = dtd->dtd_u.dtu_members;
dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
 {
-  if (get_btf_id (dmd->dmd_type) > BTF_MAX_TYPE)
-continue;
-  if (strcmp (dmd->dmd_name, name) == 0)
-return i;
-  i++;
+ bool field_has_btf = get_btf_id (dmd->dmd_type) <= BTF_MAX_TYPE;
+
+ if (field == node)
+   return field_has_btf ? i : -1;
+
+ if (field_has_btf)
+   i++;
+
+ field = DECL_CHAIN (field);
 }
 }
   return -1;
diff --git a/gcc/testsuite/gcc.target/bpf/core-pr106745.c 
b/gcc/testsuite/gcc.target/bpf/core-pr106745.c
new file mode 100644
index 000..9d347006a69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-pr106745.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA -mco-re" } */
+
+struct weird
+{
+  struct
+  {
+int b;
+  };
+
+  char x;
+
+  union
+  {
+int a;
+int c;
+  };
+};
+
+
+int test (struct weird *arg) {
+  int *x = __builtin_preserve_access_index (&arg->b);
+  int *y = __builtin_preserve_access_index (&arg->c);
+
+  return *x + *y;
+}
+
+
+/* { dg-final { scan-assembler-times "ascii \"0:0:0.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2:1.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
-- 
2.36.1



Re: [PATCH] bpf: handle anonymous members in CO-RE reloc [PR106745]

2022-08-29 Thread David Faust via Gcc-patches



On 8/29/22 12:57, Jose E. Marchesi wrote:
> 
> Hi David.
> 
>> The old method for computing a member index for a CO-RE relocation
>> relied on a name comparison, which could SEGV if the member in question
>> is itself part of an anonymous inner struct or union.
>>
>> This patch changes the index computation to not rely on a name, while
>> maintaining the ability to account for other sibling fields which may
>> not have a representation in BTF.
>>
>> Tested in bpf-unknown-none, no known regressions.
>> OK?
>>
>> Thanks.
>>
>> gcc/ChangeLog:
>>
>>  PR target/106745
>>  * config/bpf/coreout.cc (bpf_core_get_sou_member_index): Fix
>>  computation of index for anonymous members.
>>
>> gcc/testsuite/ChangeLog:
>>
>>  PR target/106745
>>  * gcc.target/bpf/core-pr106745.c: New test.
>> ---
>>  gcc/config/bpf/coreout.cc| 19 +
>>  gcc/testsuite/gcc.target/bpf/core-pr106745.c | 30 
>>  2 files changed, 44 insertions(+), 5 deletions(-)
>>  create mode 100644 gcc/testsuite/gcc.target/bpf/core-pr106745.c
>>
>> diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
>> index cceaaa969cc..caad4380fa1 100644
>> --- a/gcc/config/bpf/coreout.cc
>> +++ b/gcc/config/bpf/coreout.cc
>> @@ -207,7 +207,6 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, 
>> const tree node)
>>if (TREE_CODE (node) == FIELD_DECL)
>>  {
>>const tree container = DECL_CONTEXT (node);
>> -  const char * name = IDENTIFIER_POINTER (DECL_NAME (node));
>>  
>>/* Lookup the CTF type info for the containing type.  */
>>dw_die_ref die = lookup_type_die (container);
>> @@ -222,16 +221,26 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, 
>> const tree node)
>>if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
>>  return -1;
>>  
>> +  tree field = TYPE_FIELDS (container);
>>int i = 0;
>>ctf_dmdef_t * dmd;
>>for (dmd = dtd->dtd_u.dtu_members;
>> dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
>>  {
>>if (get_btf_id (dmd->dmd_type) > BTF_MAX_TYPE)
>> -continue;
>> -  if (strcmp (dmd->dmd_name, name) == 0)
>> -return i;
>> -  i++;
>> +{
>> +  /* This field does not have a BTF representation.  */
>> +  if (field == node)
>> +return -1;
>> +}
>> +  else
>> +{
>> +  if (field == node)
>> +return i;
>> +  i++;
>> +}
>> +
>> +  field = DECL_CHAIN (field);
>>  }
> 
> I find the logic of the new conditional a little difficult to follow.
> What about something like this instead:
> 
> for (dmd = dtd->dtd_u.dtu_members;
>  dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
>   {
> bool field_has_btf = get_btf_id (dmd->dmd_type) <= BTF_MAX_TYPE;
> 
> if (field == node)
>   return field_has_btf ? i : -1;
> 
> if (field_has_btf)
>   i++;
> field = DECL_CHAIN (field);
>   }
> 
> WDYT?

Thanks, that is certainly easier to follow.

v2 coming shortly.


> 
>>  }
>>return -1;
>> diff --git a/gcc/testsuite/gcc.target/bpf/core-pr106745.c 
>> b/gcc/testsuite/gcc.target/bpf/core-pr106745.c
>> new file mode 100644
>> index 000..9d347006a69
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.target/bpf/core-pr106745.c
>> @@ -0,0 +1,30 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O0 -gbtf -dA -mco-re" } */
>> +
>> +struct weird
>> +{
>> +  struct
>> +  {
>> +int b;
>> +  };
>> +
>> +  char x;
>> +
>> +  union
>> +  {
>> +int a;
>> +int c;
>> +  };
>> +};
>> +
>> +
>> +int test (struct weird *arg) {
>> +  int *x = __builtin_preserve_access_index (&arg->b);
>> +  int *y = __builtin_preserve_access_index (&arg->c);
>> +
>> +  return *x + *y;
>> +}
>> +
>> +
>> +/* { dg-final { scan-assembler-times "ascii \"0:0:0.0\"\[\t 
>> \]+\[^\n\]*btf_aux_string" 1 } } */
>> +/* { dg-final { scan-assembler-times "ascii \"0:2:1.0\"\[\t 
>> \]+\[^\n\]*btf_aux_string" 1 } } */


[PATCH] bpf: handle anonymous members in CO-RE reloc [PR106745]

2022-08-29 Thread David Faust via Gcc-patches
The old method for computing a member index for a CO-RE relocation
relied on a name comparison, which could SEGV if the member in question
is itself part of an anonymous inner struct or union.

This patch changes the index computation to not rely on a name, while
maintaining the ability to account for other sibling fields which may
not have a representation in BTF.

Tested in bpf-unknown-none, no known regressions.
OK?

Thanks.

gcc/ChangeLog:

PR target/106745
* config/bpf/coreout.cc (bpf_core_get_sou_member_index): Fix
computation of index for anonymous members.

gcc/testsuite/ChangeLog:

PR target/106745
* gcc.target/bpf/core-pr106745.c: New test.
---
 gcc/config/bpf/coreout.cc| 19 +
 gcc/testsuite/gcc.target/bpf/core-pr106745.c | 30 
 2 files changed, 44 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/bpf/core-pr106745.c

diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
index cceaaa969cc..caad4380fa1 100644
--- a/gcc/config/bpf/coreout.cc
+++ b/gcc/config/bpf/coreout.cc
@@ -207,7 +207,6 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, 
const tree node)
   if (TREE_CODE (node) == FIELD_DECL)
 {
   const tree container = DECL_CONTEXT (node);
-  const char * name = IDENTIFIER_POINTER (DECL_NAME (node));
 
   /* Lookup the CTF type info for the containing type.  */
   dw_die_ref die = lookup_type_die (container);
@@ -222,16 +221,26 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, 
const tree node)
   if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
 return -1;
 
+  tree field = TYPE_FIELDS (container);
   int i = 0;
   ctf_dmdef_t * dmd;
   for (dmd = dtd->dtd_u.dtu_members;
dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
 {
   if (get_btf_id (dmd->dmd_type) > BTF_MAX_TYPE)
-continue;
-  if (strcmp (dmd->dmd_name, name) == 0)
-return i;
-  i++;
+   {
+ /* This field does not have a BTF representation.  */
+ if (field == node)
+   return -1;
+   }
+ else
+   {
+ if (field == node)
+   return i;
+ i++;
+   }
+
+ field = DECL_CHAIN (field);
 }
 }
   return -1;
diff --git a/gcc/testsuite/gcc.target/bpf/core-pr106745.c 
b/gcc/testsuite/gcc.target/bpf/core-pr106745.c
new file mode 100644
index 000..9d347006a69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/core-pr106745.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -gbtf -dA -mco-re" } */
+
+struct weird
+{
+  struct
+  {
+int b;
+  };
+
+  char x;
+
+  union
+  {
+int a;
+int c;
+  };
+};
+
+
+int test (struct weird *arg) {
+  int *x = __builtin_preserve_access_index (&arg->b);
+  int *y = __builtin_preserve_access_index (&arg->c);
+
+  return *x + *y;
+}
+
+
+/* { dg-final { scan-assembler-times "ascii \"0:0:0.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
+/* { dg-final { scan-assembler-times "ascii \"0:2:1.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
-- 
2.36.1



Re: [PATCH] btf: do not use the CHAR `encoding' bit for BTF

2022-08-02 Thread David Faust via Gcc-patches



On 8/2/22 08:42, Jose E. Marchesi wrote:
> 
>> On 7/26/22 14:58, Indu Bhagat wrote:
>>> On 7/22/22 4:23 AM, Jose E. Marchesi via Gcc-patches wrote:

 Contrary to CTF and our previous expectations, as per [1], turns out
 that in BTF:

 1) The `encoding' field in integer types shall not be treated as a
 bitmap, but as an enumerated, i.e. these bits are exclusive to each
 other.

 2) The CHAR bit in `encoding' shall _not_ be set when emitting types
 for char nor `unsigned char'.

>>>
>>> Hmm...well.  At this time, I suggest we make a note of this in the btf.h 
>>> for posterity that BTF_INT_CHAR is to not be used (i.e., BTF_INT_CHAR 
>>> should not be set for char / unsigned char).
>>
>> Agreed it would be good to add this note.
> 
> Hmm, I am not sure such a comment actually belongs to include/btf.h,
> which is not specific to the compiler and is supposed to reflect the BTF
> format per-se.  The CHAR bit is documented in the kernel documentation
> and it may be used at some point by bpflib, or who knows what.

OK you make a good point.

In that case the patch LGTM to commit. Thanks!

> 
> That's why I put the comment in btfout.cc instead, to make it clear that
> BTF_INT_CHAR is indeed not to be set for char / unsigned char by the
> compiler:
> 
 +  /* In BTF the CHAR `encoding' seems to not be used, so clear it
 + here.  */
 +  dtd->dtd_u.dtu_enc.cte_format &= ~BTF_INT_CHAR;


Re: [PATCH] btf: do not use the CHAR `encoding' bit for BTF

2022-08-01 Thread David Faust via Gcc-patches



On 7/26/22 14:58, Indu Bhagat wrote:
> On 7/22/22 4:23 AM, Jose E. Marchesi via Gcc-patches wrote:
>>
>> Contrary to CTF and our previous expectations, as per [1], turns out
>> that in BTF:
>>
>> 1) The `encoding' field in integer types shall not be treated as a
>> bitmap, but as an enumerated, i.e. these bits are exclusive to each
>> other.
>>
>> 2) The CHAR bit in `encoding' shall _not_ be set when emitting types
>> for char nor `unsigned char'.
>>
> 
> Hmm...well.  At this time, I suggest we make a note of this in the btf.h 
> for posterity that BTF_INT_CHAR is to not be used (i.e., BTF_INT_CHAR 
> should not be set for char / unsigned char).

Agreed it would be good to add this note.

> 
>> Consequently this patch clears the CHAR bit before emitting the
>> variable part of BTF integral types.  It also updates the testsuite
>> accordingly, expanding it to check for BOOL bits.
>>
>> [1] 
>> https://lore.kernel.org/bpf/a73586ad-f2dc-0401-1eba-2004357b7...@fb.com/T/#t
>>
>> gcc/ChangeLog:
>>
>>  * btfout.cc (output_asm_btf_vlen_bytes): Do not use the CHAR
>>  encoding bit in BTF.
>>
>> gcc/testsuite/ChangeLog:
>>
>>  * gcc.dg/debug/btf/btf-int-1.c: Do not check for char bits in
>>  bti_encoding and check for bool bits.
>> ---
>>   gcc/btfout.cc  |  4 
>>   gcc/testsuite/gcc.dg/debug/btf/btf-int-1.c | 18 +++---
>>   2 files changed, 15 insertions(+), 7 deletions(-)
>>
>> diff --git a/gcc/btfout.cc b/gcc/btfout.cc
>> index 31af50521da..576f73d47cf 100644
>> --- a/gcc/btfout.cc
>> +++ b/gcc/btfout.cc
>> @@ -914,6 +914,10 @@ output_asm_btf_vlen_bytes (ctf_container_ref ctfc, 
>> ctf_dtdef_ref dtd)
>> if (dtd->dtd_data.ctti_size < 1)
>>  break;
>>   
>> +  /* In BTF the CHAR `encoding' seems to not be used, so clear it
>> + here.  */
>> +  dtd->dtd_u.dtu_enc.cte_format &= ~BTF_INT_CHAR;
>> +
> 
> [Added David Faust]
> 
> What do you think about doing this in btf_dtd_emit_preprocess_cb () for 
> types where kind == BTF_KIND_INT. This is the place where BTF specific 
> massaging of type info takes place.

Sorry for the delay.

I think this could be done in either place. I lean slightly in favor
of doing it here as implemented in this patch. Other integer encodings
are not specifically massaged into BTF; we leave the in-memory
representation the same as CTF and just write them out according to the
BTF rules since both formats hold the same information, and this function
is where we do that.

In my opinion, this is a similar case. It is not wrong hold on to the
information (internally) that this is a char type, rather it is a quirk
of the other BTF encoding rules which means it _is_ wrong to ever set the
bit saying as much when writing the BTF info (at least for now...).

So, this patch LGTM, but please add a brief note in btf.h that the CHAR
flag is currently not to be used.

Thanks

> 
>> encoding = BTF_INT_DATA (dtd->dtd_u.dtu_enc.cte_format,
>> dtd->dtd_u.dtu_enc.cte_offset,
>> dtd->dtd_u.dtu_enc.cte_bits);
>> diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-int-1.c 
>> b/gcc/testsuite/gcc.dg/debug/btf/btf-int-1.c
>> index 2381decd6ff..87d9758e9cb 100644
>> --- a/gcc/testsuite/gcc.dg/debug/btf/btf-int-1.c
>> +++ b/gcc/testsuite/gcc.dg/debug/btf/btf-int-1.c
>> @@ -4,7 +4,8 @@
>>  | 0 | encoding | offset | 00 | bits |
>>  encoding:
>>signed  1 << 24
>> - char2 << 24
>> + char2 << 24  (not used)
>> + bool4 << 24
>>   
>>  All offsets in this test should be 0.
>>  This test does _not_ check number of bits, as it may vary between 
>> targets.
>> @@ -13,13 +14,14 @@
>>   /* { dg-do compile } */
>>   /* { dg-options "-O0 -gbtf -dA" } */
>>   
>> -/* Check for 8 BTF_KIND_INT types.  */
>> -/* { dg-final { scan-assembler-times "\[\t \]0x100\[\t 
>> \]+\[^\n\]*btt_info" 8 } } */
>> +/* Check for 9 BTF_KIND_INT types.  */
>> +/* { dg-final { scan-assembler-times "\[\t \]0x100\[\t 
>> \]+\[^\n\]*btt_info" 9 } } */
>>   
>> -/* Check the signed/char flags, but not bit size. */
>> -/* { dg-final { scan-assembler-times "\[\t \]0x1..\[\t 
>> \]+\[^\n\]*bti_encoding" 3 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]0x2..\[\t 
>> \]+\[^\n\]*bti_encoding" 1 } } */
>> -/* { dg-final { scan-assembler-times "\[\t \]0x3..\[\t 
>> \]+\[^\n\]*bti_encoding" 1 } } */
>> +/* Check the signed flags, but not bit size. */
>> +/* { dg-final { scan-assembler-times "\[\t \]0x1..\[\t 
>> \]+\[^\n\]*bti_encoding" 4 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]0x..\[\t 
>> \]+\[^\n\]*bti_encoding" 3 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]0x.\[\t 
>> \]+\[^\n\]*bti_encoding" 1 } } */
>> +/* { dg-final { scan-assembler-times "\[\t \]0x4..\[\t 
>> \]+\[^\n\]*bti_encoding" 1 } } */
>>   
>>   /* Check that there is a string entry for each type name.  */
>>   /* { dg-final { sca

Re: [PATCH V2] btf: emit linkage information in BTF_KIND_FUNC entries

2022-07-27 Thread David Faust via Gcc-patches



On 7/12/22 08:13, Jose E. Marchesi via Gcc-patches wrote:
> 
> The kernel bpftool expects BTF_KIND_FUNC entries in BTF to include an
> annotation reflecting the linkage of functions (static, global).  For
> whatever reason they abuse the `vlen' field of the BTF_KIND_FUNC entry
> instead of adding a variable-part to the record like it is done with
> other entry kinds.
> 
> This patch makes GCC to include this linkage info in BTF_KIND_FUNC
> entries.
> 
> Tested in bpf-unknown-none target.

LGTM
Thanks.

> 
> gcc/ChangeLog:
> 
>   PR debug/106263
>   * ctfc.h (struct ctf_dtdef): Add field linkage.
>   * ctfc.cc (ctf_add_function): Set ctti_linkage.
>   * dwarf2ctf.cc (gen_ctf_function_type): Pass a linkage for
>   function types and subprograms.
>   * btfout.cc (btf_asm_func_type): Emit linkage information for the
>   function.
>   (btf_dtd_emit_preprocess_cb): Propagate the linkage information
>   for functions.
> 
> gcc/testsuite/ChangeLog:
> 
>   PR debug/106263
>   * gcc.dg/debug/btf/btf-function-4.c: New test.
>   * gcc.dg/debug/btf/btf-function-5.c: Likewise.
> ---
>  gcc/btfout.cc   |  6 +-
>  gcc/ctfc.cc |  3 ++-
>  gcc/ctfc.h  |  3 ++-
>  gcc/dwarf2ctf.cc|  4 +++-
>  gcc/testsuite/gcc.dg/debug/btf/btf-function-4.c | 14 ++
>  gcc/testsuite/gcc.dg/debug/btf/btf-function-5.c | 14 ++
>  6 files changed, 40 insertions(+), 4 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-function-4.c
>  create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-function-5.c
> 
> diff --git a/gcc/btfout.cc b/gcc/btfout.cc
> index 31af50521da..594cba84910 100644
> --- a/gcc/btfout.cc
> +++ b/gcc/btfout.cc
> @@ -463,6 +463,7 @@ btf_dtd_emit_preprocess_cb (ctf_container_ref ctfc, 
> ctf_dtdef_ref dtd)
>ctf_dtdef_ref func_dtd = ggc_cleared_alloc ();
>func_dtd->dtd_data = dtd->dtd_data;
>func_dtd->dtd_data.ctti_type = dtd->dtd_type;
> +  func_dtd->linkage = dtd->linkage;
>  
>vec_safe_push (funcs, func_dtd);
>num_types_created++;
> @@ -740,7 +741,10 @@ static void
>  btf_asm_func_type (ctf_dtdef_ref dtd)
>  {
>dw2_asm_output_data (4, dtd->dtd_data.ctti_name, "btt_name");
> -  dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_FUNC, 0, 0), "btt_info");
> +  dw2_asm_output_data (4, BTF_TYPE_INFO (BTF_KIND_FUNC, 0,
> + dtd->linkage),
> +   "btt_info: kind=%u, kflag=%u, linkage=%u",
> +   BTF_KIND_FUNC, 0, dtd->linkage);
>dw2_asm_output_data (4, get_btf_id (dtd->dtd_data.ctti_type), "btt_type");
>  }
>  
> diff --git a/gcc/ctfc.cc b/gcc/ctfc.cc
> index f24e7bff948..9773358a475 100644
> --- a/gcc/ctfc.cc
> +++ b/gcc/ctfc.cc
> @@ -777,7 +777,7 @@ ctf_add_function_arg (ctf_container_ref ctfc, dw_die_ref 
> func,
>  ctf_id_t
>  ctf_add_function (ctf_container_ref ctfc, uint32_t flag, const char * name,
> const ctf_funcinfo_t * ctc, dw_die_ref die,
> -   bool from_global_func)
> +   bool from_global_func, int linkage)
>  {
>ctf_dtdef_ref dtd;
>ctf_id_t type;
> @@ -791,6 +791,7 @@ ctf_add_function (ctf_container_ref ctfc, uint32_t flag, 
> const char * name,
>type = ctf_add_generic (ctfc, flag, name, &dtd, die);
>  
>dtd->from_global_func = from_global_func;
> +  dtd->linkage = linkage;
>dtd->dtd_data.ctti_info = CTF_TYPE_INFO (CTF_K_FUNCTION, flag, vlen);
>/* Caller must make sure CTF types for ctc->ctc_return are already added.  
> */
>dtd->dtd_data.ctti_type = (uint32_t) ctc->ctc_return;
> diff --git a/gcc/ctfc.h b/gcc/ctfc.h
> index 001e544ef08..bcf3a43ae1b 100644
> --- a/gcc/ctfc.h
> +++ b/gcc/ctfc.h
> @@ -161,6 +161,7 @@ struct GTY ((for_user)) ctf_dtdef
>ctf_itype_t dtd_data;/* Type node.  */
>bool from_global_func; /* Whether this type was added from a global
>   function.  */
> +  uint32_t linkage;   /* Used in function types.  0=local, 1=global. 
>  */
>union GTY ((desc ("ctf_dtu_d_union_selector (&%1)")))
>{
>  /* struct, union, or enum.  */
> @@ -423,7 +424,7 @@ extern ctf_id_t ctf_add_forward (ctf_container_ref, 
> uint32_t, const char *,
>  extern ctf_id_t ctf_add_typedef (ctf_container_ref, uint32_t, const char *,
>ctf_id_t, dw_die_ref);
>  extern ctf_id_t ctf_add_function (ctf_container_ref, uint32_t, const char *,
> -   const ctf_funcinfo_t *, dw_die_ref, bool);
> +   const ctf_funcinfo_t *, dw_die_ref, bool, 
> int);
>  extern ctf_id_t ctf_add_sou (ctf_container_ref, uint32_t, const char *,
>uint32_t, size_t, dw_die_ref);
>  
> diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
> index a6329ab6ee4..39714c2 100644
> --- 

[committed] MAINTAINERS: Add myself as CTF and BTF reviewer

2022-07-27 Thread David Faust via Gcc-patches
ChangeLog:

* MAINTAINERS: Add myself as reviewer for CTF and BTF.
---
 MAINTAINERS | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7408396471f..1a37f4419b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -267,6 +267,7 @@ arc portClaudiu Zissulescu  

 callgraph  Martin Liska
 callgraph  Martin Jambor   
 C front endMarek Polacek   
+CTF, BTF   David Faust 
 dataflow   Paolo Bonzini   
 dataflow   Seongbae Park   
 dataflow   Kenneth Zadeck  
@@ -397,7 +398,6 @@ Doug Evans  

 Chris Fairles  
 Alessandro Fanfarillo  
 Changpeng Fang 
-David Faust
 Sam Feifer 
 Li Feng
 Thomas Fitzsimmons 
-- 
2.36.1



Re: [PATCH 0/9] Add debug_annotate attributes

2022-06-15 Thread David Faust via Gcc-patches



On 6/14/22 22:53, Yonghong Song wrote:
> 
> 
> On 6/7/22 2:43 PM, David Faust wrote:
>> Hello,
>>
>> This patch series adds support for:
>>
>> - Two new C-language-level attributes that allow to associate (to "annotate" 
>> or
>>to "tag") particular declarations and types with arbitrary strings. As
>>explained below, this is intended to be used to, for example, characterize
>>certain pointer types.
>>
>> - The conveyance of that information in the DWARF output in the form of a new
>>DIE: DW_TAG_GNU_annotation.
>>
>> - The conveyance of that information in the BTF output in the form of two new
>>kinds of BTF objects: BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG.
>>
>> All of these facilities are being added to the eBPF ecosystem, and support 
>> for
>> them exists in some form in LLVM.
>>
>> Purpose
>> ===
>>
>> 1)  Addition of C-family language constructs (attributes) to specify 
>> free-text
>>  tags on certain language elements, such as struct fields.
>>
>>  The purpose of these annotations is to provide additional information 
>> about
>>  types, variables, and function parameters of interest to the kernel. A
>>  driving use case is to tag pointer types within the linux kernel and 
>> eBPF
>>  programs with additional semantic information, such as '__user' or 
>> '__rcu'.
>>
>>  For example, consider the linux kernel function do_execve with the
>>  following declaration:
>>
>>static int do_execve(struct filename *filename,
>>   const char __user *const __user *__argv,
>>   const char __user *const __user *__envp);
>>
>>  Here, __user could be defined with these annotations to record semantic
>>  information about the pointer parameters (e.g., they are user-provided) 
>> in
>>  DWARF and BTF information. Other kernel facilites such as the eBPF 
>> verifier
>>  can read the tags and make use of the information.
>>
>> 2)  Conveying the tags in the generated DWARF debug info.
>>
>>  The main motivation for emitting the tags in DWARF is that the Linux 
>> kernel
>>  generates its BTF information via pahole, using DWARF as a source:
>>
>>  ++  BTF  BTF   +--+
>>  | pahole |---> vmlinux.btf --->| verifier |
>>  ++ +--+
>>  ^^
>>  ||
>>DWARF |BTF |
>>  ||
>>   vmlinux  +-+
>>   module1.ko   | BPF program |
>>   module2.ko   +-+
>> ...
>>
>>  This is because:
>>
>>  a)  Unlike GCC, LLVM will only generate BTF for BPF programs.
>>
>>  b)  GCC can generate BTF for whatever target with -gbtf, but there is no
>>  support for linking/deduplicating BTF in the linker.
>>
>>  In the scenario above, the verifier needs access to the pointer tags of
>>  both the kernel types/declarations (conveyed in the DWARF and translated
>>  to BTF by pahole) and those of the BPF program (available directly in 
>> BTF).
>>
>>  Another motivation for having the tag information in DWARF, unrelated to
>>  BPF and BTF, is that the drgn project (another DWARF consumer) also 
>> wants
>>  to benefit from these tags in order to differentiate between different
>>  kinds of pointers in the kernel.
>>
>> 3)  Conveying the tags in the generated BTF debug info.
>>
>>  This is easy: the main purpose of having this info in BTF is for the
>>  compiled eBPF programs. The kernel verifier can then access the tags
>>  of pointers used by the eBPF programs.
>>
>>
>> For more information about these tags and the motivation behind them, please
>> refer to the following linux kernel discussions:
>>
>>https://lore.kernel.org/bpf/20210914223004.244411-1-...@fb.com/
>>https://lore.kernel.org/bpf/20211012164838.3345699-1-...@fb.com/
>>https://lore.kernel.org/bpf/2022012604.1504583-1-...@fb.com/
>>
>>
>> Implementation Overview
>> ===
>>
>> To enable these annotations, two new C language attributes are added:
>> __attribute__((debug_annotate_decl("foo"))) and
>> __attribute__((debug_annotate_type("bar"))). Both attributes accept a single
>> arbitrary string constant argument, which will be recorded in the generated
>> DWARF and/or BTF debug information. They have no effect on code generation.
>>
>> Note that we are not using the same attribute names as LLVM (btf_decl_tag and
>> btf_type_tag, respectively). While these attributes are functionally very
>> similar, they have grown beyond purely BTF-specific uses, so inclusion of 
>> "btf"
>> in the attribute name seems misleading.
>>
>> DWARF support is enabled via a new DW_TAG_GNU_annotati

[PATCH 8/9] doc: document new attributes

2022-06-07 Thread David Faust via Gcc-patches
gcc/

* doc/extend.texi (Common Function Attributes): Document
debug_annotate_decl attribute.
(Common Variable Attributes): Likewise.
(Common Type Attributes): Likewise. Also document
debug_annotate_type attribute.
---
 gcc/doc/extend.texi | 106 
 1 file changed, 106 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a2e2a303ff1..a4c114f0e81 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -2931,6 +2931,30 @@ extern __attribute__ ((alloc_size (1), malloc, nothrow))
 StrongAlias (allocate, alloc);
 @end smallexample
 
+@item debug_annotate_decl (@var{annotation})
+@cindex @code{debug_annotate_decl} function attribute
+The @code{debug_annotate_decl} attribute is used to add arbitrary
+string annotations to the debugging information produced for a given
+declaration. The attribute accepts a single string argument, and may be
+specified multiple times for a single declaration. The behavior is
+to record the string argument in debug information generated for the
+declaration. Currently, DWARF and BTF debug information are supported.
+There is no effect on code generation; the attribute has no effect at
+all if neither DWARF nor BTF are output.
+
+@smallexample
+int foo (int a, int b) __attribute__((debug_annotate_decl ("my_tag")));
+@end smallexample
+
+@noindent
+results in a DW_TAG_GNU_annotation DIE associating the string ``my_tag''
+to the function ``foo'', and/or a BTF_KIND_DECL_TAG BTF record to the
+same effect.
+
+The @code{debug_annotate_decl} attribute can also be used for
+variables and types (@pxref{Common Variable Attributes},
+@pxref{Common Type Attributes}.)
+
 @item deprecated
 @itemx deprecated (@var{msg})
 @cindex @code{deprecated} function attribute
@@ -7510,6 +7534,42 @@ but not attributes that affect a symbol's linkage or 
visibility such as
 attribute is also not copied.  @xref{Common Function Attributes}.
 @xref{Common Type Attributes}.
 
+@item debug_annotate_decl (@var{annotation})
+@cindex @code{debug_annotate_decl} variable attribute
+The @code{debug_annotate_decl} attribute is used to add arbitrary
+string annotations to the debugging information produced for a given
+declaration. The attribute accepts a single string argument, and may be
+specified multiple times for a single declaration. The behavior is
+to record the string argument in debug information generated for the
+declaration. Currently, DWARF and BTF debug information are supported.
+There is no effect on code generation; the attribute has no effect at
+all if neither DWARF nor BTF are output.
+
+@smallexample
+int my_var __attribute__((debug_annotate_decl ("my_tag")))
+@end smallexample
+
+@noindent
+results in a DW_TAG_GNU_annotation DIE associating the string ``my_tag''
+to the ``my_var'', and/or a BTF_KIND_DECL_TAG BTF record to the same
+effect.
+
+Annotations can be specified for declarations other than variables,
+such as struct fields. For example:
+
+@smallexample
+struct foo @{
+  int * x __attribute__ ((debug_annotate_decl ("my_tag")));
+@};
+@end smallexample
+has similar results, producing debug info which associates the string
+``my_tag'' to the struct field ``x''.
+
+@noindent
+The @code{debug_annotate_decl} attribute can also be used for
+functions and types (@pxref{Common Function Attributes},
+@pxref{Common Type Attributes}.)
+
 @item deprecated
 @itemx deprecated (@var{msg})
 @cindex @code{deprecated} variable attribute
@@ -8593,6 +8653,52 @@ A @{ /* @r{@dots{}} */ @};
 struct __attribute__ ((copy ( (struct A *)0)) B @{ /* @r{@dots{}} */ @};
 @end smallexample
 
+@item debug_annotate_decl (@var{annotation})
+@cindex @code{debug_annotate_decl} type attribute
+The @code{debug_annotate_decl} attribute is used to add arbitrary
+string annotations to the debugging information produced for a given
+type declaration. The attribute accepts a single string argument, and
+may be specified multiple times for a type declaration. The behavior
+is to record the string argument in the debug information generated
+for the declaration. Currently, DWARF and BTF debug information are
+supported. There is no effect on code generation; the attribute has no
+effect at all if neither DWARF nor BTF are output.
+
+@smallexample
+struct t @{
+/* @r{@dots{}} */
+@} __attribute__((debug_annotate_decl ("my_tag")));
+@end smallexample
+
+@noindent
+results in a DW_TAG_GNU_annotation DIE associating the string
+``my_tag'' to the ``struct t'', and/or a BTF_KIND_DECL_TAG BTF record
+to the same effect.
+
+The @code{debug_annotate_decl} attribute can also be used for
+variables and functions (@pxref{Common Variable Attributes},
+@pxref{Common Function Attributes}.)
+
+@item debug_annotate_type (@var{annotation})
+@cindex @code{debug_annotate_type} type attribute
+The @code{debug_annotate_type} attribute is used to add arbitrary
+string annotations to the debugging information produced for a given
+type. The attribute

[PATCH 9/9] testsuite: add debug annotation tests

2022-06-07 Thread David Faust via Gcc-patches
This patch adds tests for debug annotations, in BTF and in DWARF.

gcc/testsuite/

* gcc.dg/debug/btf/btf-decltag-func.c: New test.
* gcc.dg/debug/btf/btf-decltag-sou.c: Likewise.
* gcc.dg/debug/btf/btf-decltag-typedef.c: Likewise.
* gcc.dg/debug/btf/btf-typetag-1.c: Likewise.
* gcc.dg/debug/dwarf2/annotation-1.c: Likewise.
* gcc.dg/debug/dwarf2/annotation-2.c: Likewise.
* gcc.dg/debug/dwarf2/annotation-3.c: Likewise.
* gcc.dg/debug/dwarf2/annotation-4.c: Likewise.
---
 .../gcc.dg/debug/btf/btf-decltag-func.c   | 18 ++
 .../gcc.dg/debug/btf/btf-decltag-sou.c| 34 +++
 .../gcc.dg/debug/btf/btf-decltag-typedef.c| 15 
 .../gcc.dg/debug/btf/btf-typetag-1.c  | 20 +++
 .../gcc.dg/debug/dwarf2/annotation-1.c| 20 +++
 .../gcc.dg/debug/dwarf2/annotation-2.c| 17 ++
 .../gcc.dg/debug/dwarf2/annotation-3.c| 20 +++
 .../gcc.dg/debug/dwarf2/annotation-4.c| 34 +++
 8 files changed, 178 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-typetag-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-3.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-4.c

diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
new file mode 100644
index 000..b2d6820cf23
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
@@ -0,0 +1,18 @@
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 4 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+
+#define __tag1 __attribute__((debug_annotate_decl("decl-tag-1")))
+#define __tag2 __attribute__((debug_annotate_decl("decl-tag-2")))
+#define __tag3 __attribute__((debug_annotate_decl("decl-tag-3")))
+
+extern int bar (int __tag1, int __tag2) __tag3;
+
+int __tag1 __tag2 foo (int arg1, int *arg2 __tag2)
+  {
+return bar (arg1 + 1, *arg2 + 2);
+  }
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
new file mode 100644
index 000..bb125b53ce7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
@@ -0,0 +1,34 @@
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 16 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*decltag_compidx" 
2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 6 } } */
+
+#define __tag1 __attribute__((debug_annotate_decl("decl-tag-1")))
+#define __tag2 __attribute__((debug_annotate_decl("decl-tag-2")))
+#define __tag3 __attribute__((debug_annotate_decl("decl-tag-3")))
+
+struct t {
+  int a;
+  long b __tag3;
+  char c __tag2 __tag3;
+} __tag1 __tag2;
+
+struct t my_t __tag1 __tag3;
+
+
+union u {
+  char one __tag1 __tag2;
+  short two;
+  int three __tag1;
+  long four __tag1 __tag2 __tag3;
+  long long five __tag2;
+} __tag3;
+
+union u my_u __tag2;
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c
new file mode 100644
index 000..6a44aaf9623
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c
@@ -0,0 +1,15 @@
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+
+#define __tag1 __attribute__((debug_annotate_decl("decl-tag-1")))
+#define __tag2 __attribute__((debug_annotate_decl("decl-tag-2")))
+#define __tag3 __attribute__((debug_annotate_decl("decl-tag-3")))
+
+struct s { int a; } __tag1;
+
+typedef struct s * sptr __tag2;
+
+sptr my_sptr __tag3;
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-typetag-1.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-typetag-

[PATCH 6/9] dwarf2ctf: convert annotation DIEs to CTF types

2022-06-07 Thread David Faust via Gcc-patches
This patch makes the DWARF-to-CTF conversion process aware of the new
DW_TAG_GNU annotation DIEs. The DIEs are converted to an internal-only
CTF representation as appropriate and added to the compilation unit CTF
container.

gcc/

* dwarf2ctf.cc (handle_debug_annotations): New function.
(gen_ctf_sou_type): Call it here, if appropriate. Don't try to
create member types for children that are not DW_TAG_member.
(gen_ctf_function_type): Call handle_debug_annotations if
appropriate.
(gen_ctf_variable): Likewise.
(gen_ctf_function): Likewise.
(gen_ctf_type): Likewise.
---
 gcc/dwarf2ctf.cc | 112 ++-
 1 file changed, 111 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
index 393aa92d71d..65714e5d3b9 100644
--- a/gcc/dwarf2ctf.cc
+++ b/gcc/dwarf2ctf.cc
@@ -32,6 +32,12 @@ along with GCC; see the file COPYING3.  If not see
 static ctf_id_t
 gen_ctf_type (ctf_container_ref, dw_die_ref);
 
+static void
+gen_ctf_variable (ctf_container_ref, dw_die_ref);
+
+static void
+handle_debug_annotations (ctf_container_ref, dw_die_ref, ctf_id_t, int);
+
 /* All the DIE structures we handle come from the DWARF information
generated by GCC.  However, there are three situations where we need
to create our own created DIE structures because GCC doesn't
@@ -547,6 +553,7 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
   /* Now process the struct members.  */
   {
 dw_die_ref c;
+int idx = 0;
 
 c = dw_get_die_child (sou);
 if (c)
@@ -559,6 +566,12 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
 
  c = dw_get_die_sib (c);
 
+ if (dw_get_die_tag (c) != DW_TAG_member)
+   continue;
+
+ if (c == dw_get_die_child (sou))
+   idx = 0;
+
  field_name = get_AT_string (c, DW_AT_name);
  field_type = ctf_get_AT_type (c);
  field_location = ctf_get_AT_data_member_location (c);
@@ -626,6 +639,12 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
 field_name,
 field_type_id,
 field_location);
+
+ /* Handle BTF tags on the member.  */
+ if (btf_debuginfo_p ())
+   handle_debug_annotations (ctfc, c, sou_type_id, idx);
+
+ idx++;
}
   while (c != dw_get_die_child (sou));
   }
@@ -716,6 +735,9 @@ gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref 
function,
  arg_type = gen_ctf_type (ctfc, ctf_get_AT_type (c));
  /* Add the argument to the existing CTF function type.  */
  ctf_add_function_arg (ctfc, function, arg_name, arg_type);
+
+ if (btf_debuginfo_p ())
+   handle_debug_annotations (ctfc, c, function_type_id, i - 1);
}
  else
/* This is a local variable.  Ignore.  */
@@ -828,6 +850,10 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
   /* Skip updating the number of global objects at this time.  This is updated
  later after pre-processing as some CTF variable records although
  generated now, will not be emitted later.  [PR105089].  */
+
+  /* Handle any BTF tags on the variable.  */
+  if (btf_debuginfo_p ())
+handle_debug_annotations (ctfc, die, CTF_NULL_TYPEID, -1);
 }
 
 /* Add a CTF function record for the given input DWARF DIE.  */
@@ -845,8 +871,12 @@ gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die)
  counter.  Note that DWARF encodes function types in both
  DW_TAG_subroutine_type and DW_TAG_subprogram in exactly the same
  way.  */
-  (void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
+  function_type_id = gen_ctf_function_type (ctfc, die, true /* 
from_global_func */);
   ctfc->ctfc_num_global_funcs += 1;
+
+  /* Handle any BTF tags on the function itself.  */
+  if (btf_debuginfo_p ())
+handle_debug_annotations (ctfc, die, function_type_id, -1);
 }
 
 /* Add CTF type record(s) for the given input DWARF DIE and return its type id.
@@ -923,6 +953,10 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
   break;
 }
 
+  /* Handle any BTF tags on the type.  */
+  if (btf_debuginfo_p () && !unrecog_die)
+handle_debug_annotations (ctfc, die, type_id, -1);
+
   /* For all types unrepresented in CTF, use an explicit CTF type of kind
  CTF_K_UNKNOWN.  */
   if ((type_id == CTF_NULL_TYPEID) && (!unrecog_die))
@@ -931,6 +965,82 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
   return type_id;
 }
 
+/* BTF support. Handle any annotations attached to a given DIE, and generate
+   intermediate CTF types for them. BTF tags are inserted into the type chain
+   at this point. The return value is the CTF type ID of the last type tag
+   created (for type chaining), or the same as the argument TYPE_ID if there 
are
+ 

[PATCH 4/9] dwarf: generate annotation DIEs

2022-06-07 Thread David Faust via Gcc-patches
The "debug_annotate_decl" and "debug_annotate_type" attributes are
handled by constructing DW_TAG_GNU_annotation DIEs. These DIEs are
children of the declarations or types which they annotate, and convey
the information via a string constant.

gcc/

* dwarf2out.cc (gen_decl_annotation_dies): New function.
(gen_type_annotation_dies): Likewise.
(modified_type_die): Call them here, if appropriate.
(gen_formal_parameter_die): Likewise.
(gen_typedef_die): Likewise.
(gen_type_die): Likewise.
(gen_decl_die): Likewise.
---
 gcc/dwarf2out.cc | 94 
 1 file changed, 94 insertions(+)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 9c61026bb34..aff9f72bd55 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -13611,6 +13611,78 @@ long_double_as_float128 (tree type)
   return NULL_TREE;
 }
 
+/* Given a tree T, which may be a decl or a type, process any
+   "debug_annotate_decl" attributes on T, provided in ATTR. Construct
+   DW_TAG_GNU_annotation DIEs appropriately as children of TARGET, usually
+   the DIE for T.  */
+
+static void
+gen_decl_annotation_dies (tree t, dw_die_ref target)
+{
+  dw_die_ref die;
+  tree attr;
+
+  if (t == NULL_TREE || !target)
+return;
+
+  if (TYPE_P (t))
+attr = lookup_attribute ("debug_annotate_decl", TYPE_ATTRIBUTES (t));
+  else if (DECL_P (t))
+attr = lookup_attribute ("debug_annotate_decl", DECL_ATTRIBUTES (t));
+  else
+/* This is an error.  */
+gcc_unreachable ();
+
+  while (attr != NULL_TREE)
+{
+  die = new_die (DW_TAG_GNU_annotation, target, t);
+  add_name_attribute (die, IDENTIFIER_POINTER (get_attribute_name (attr)));
+  add_AT_string (die, DW_AT_const_value,
+TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr;
+  attr = TREE_CHAIN (attr);
+}
+
+  /* Strip the decl tag attribute to avoid creating multiple copies if we hit
+ this tree node again in some recursive call.  */
+  if (TYPE_P (t))
+TYPE_ATTRIBUTES (t) =
+  remove_attribute ("debug_annotate_decl", TYPE_ATTRIBUTES (t));
+  else if (DECL_P (t))
+DECL_ATTRIBUTES (t) =
+  remove_attribute ("debug_annotate_decl", DECL_ATTRIBUTES (t));
+}
+
+/* Given a tree TYPE, process any "debug_annotate_type" attributes on
+   TYPE. Construct DW_TAG_GNU_annotation DIEs appropriately as children of
+   TARGET, usually the DIE for TYPE.  */
+
+static void
+gen_type_annotation_dies (tree type, dw_die_ref target)
+{
+  dw_die_ref die;
+  tree attr;
+
+  if (type == NULL_TREE || !target)
+return;
+
+  gcc_assert (TYPE_P (type));
+
+  attr = lookup_attribute ("debug_annotate_type", TYPE_ATTRIBUTES (type));
+  while (attr != NULL_TREE)
+{
+  die = new_die (DW_TAG_GNU_annotation, target, type);
+  add_name_attribute (die, IDENTIFIER_POINTER (get_attribute_name (attr)));
+  add_AT_string (die, DW_AT_const_value,
+TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr;
+  attr = TREE_CHAIN (attr);
+}
+
+  /* Strip the type tag attribute to avoid creating multiple copies if we hit
+ this type again in some recursive call.  */
+  TYPE_ATTRIBUTES (type) =
+remove_attribute ("debug_annotate_type", TYPE_ATTRIBUTES (type));
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
entry that chains the modifiers specified by CV_QUALS in front of the
given type.  REVERSE is true if the type is to be interpreted in the
@@ -14009,6 +14081,9 @@ modified_type_die (tree type, int cv_quals, bool 
reverse,
   if (TYPE_ARTIFICIAL (type))
 add_AT_flag (mod_type_die, DW_AT_artificial, 1);
 
+  /* Generate any annotation DIEs on this type.  */
+  gen_type_annotation_dies (type, mod_type_die);
+
   return mod_type_die;
 }
 
@@ -23002,6 +23077,9 @@ gen_formal_parameter_die (tree node, tree origin, bool 
emit_name_p,
   gcc_unreachable ();
 }
 
+  /* Generate any annotation DIEs for this decl.  */
+  gen_decl_annotation_dies (node, parm_die);
+
   return parm_die;
 }
 
@@ -26076,6 +26154,9 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
 
   if (get_AT (type_die, DW_AT_name))
 add_pubtype (decl, type_die);
+
+  /* Generate any annotation DIEs for the typedef.  */
+  gen_decl_annotation_dies (decl, type_die);
 }
 
 /* Generate a DIE for a struct, class, enum or union type.  */
@@ -26389,6 +26470,16 @@ gen_type_die (tree type, dw_die_ref context_die)
  if (die)
check_die (die);
}
+
+  /* Generate any annotation DIEs on the type.  */
+  dw_die_ref die = lookup_type_die (type);
+  if (die)
+   {
+ gen_type_annotation_dies (type, die);
+
+ /* "decl" annotations may also be attached to a type.  */
+ gen_decl_annotation_dies (type, die);
+   }
 }
 }
 
@@ -27145,6 +27236,9 @@ gen_decl_die (tree decl, tree origin, struct 
vlr_context *ctx,
   break;
 }
 
+  /* Generate any annotation D

[PATCH 7/9] btf: output decl_tag and type_tag records

2022-06-07 Thread David Faust via Gcc-patches
This patch updates btfout.cc to be aware of debug annotations, convert
them to BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG records, and output them
appropriately.

gcc/

* btfout.cc (get_btf_kind): Handle TYPE_TAG and DECL_TAG kinds.
(btf_calc_num_vbytes): Likewise.
(btf_asm_type): Likewise.
(output_asm_btf_vlen_bytes): Likewise.
---
 gcc/btfout.cc | 28 
 1 file changed, 28 insertions(+)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 31af50521da..f291cd925be 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -136,6 +136,8 @@ get_btf_kind (uint32_t ctf_kind)
 case CTF_K_VOLATILE: return BTF_KIND_VOLATILE;
 case CTF_K_CONST:return BTF_KIND_CONST;
 case CTF_K_RESTRICT: return BTF_KIND_RESTRICT;
+case CTF_K_TYPE_TAG: return BTF_KIND_TYPE_TAG;
+case CTF_K_DECL_TAG: return BTF_KIND_DECL_TAG;
 default:;
 }
   return BTF_KIND_UNKN;
@@ -201,6 +203,7 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
 case BTF_KIND_CONST:
 case BTF_KIND_RESTRICT:
 case BTF_KIND_FUNC:
+case BTF_KIND_TYPE_TAG:
 /* These kinds have no vlen data.  */
   break;
 
@@ -238,6 +241,10 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
   vlen_bytes += vlen * sizeof (struct btf_var_secinfo);
   break;
 
+case BTF_KIND_DECL_TAG:
+  vlen_bytes += sizeof (struct btf_decl_tag);
+  break;
+
 default:
   break;
 }
@@ -636,6 +643,22 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
   dw2_asm_output_data (4, dtd->dtd_data.ctti_size, "btt_size: %uB",
   dtd->dtd_data.ctti_size);
   return;
+case BTF_KIND_DECL_TAG:
+  {
+   /* A decl tag might refer to (be the child DIE of) a variable. Try to
+  lookup the parent DIE's CTF variable, and if it exists point to the
+  corresponding BTF variable. This is an odd construction - we have a
+  'type' which refers to a variable, rather than the reverse.  */
+   dw_die_ref parent = dw_get_die_parent (dtd->dtd_key);
+   ctf_dvdef_ref dvd = ctf_dvd_lookup (ctfc, parent);
+   if (dvd)
+ {
+   unsigned int var_id =
+ *(btf_var_ids->get (dvd)) + num_types_added + 1;
+   dw2_asm_output_data (4, var_id, "btt_type");
+   return;
+ }
+  }
 default:
   break;
 }
@@ -949,6 +972,11 @@ output_asm_btf_vlen_bytes (ctf_container_ref ctfc, 
ctf_dtdef_ref dtd)
 at this point.  */
   gcc_unreachable ();
 
+case BTF_KIND_DECL_TAG:
+  dw2_asm_output_data (4, dtd->dtd_u.dtu_btfnote.component_idx,
+  "decltag_compidx");
+  break;
+
 default:
   /* All other BTF type kinds have no variable length data.  */
   break;
-- 
2.36.1



[PATCH 5/9] ctfc: pass through debug annotations to BTF

2022-06-07 Thread David Faust via Gcc-patches
BTF generation currently relies on the internal CTF representation to
convert debug info from DWARF dies. This patch adds a new internal
header, "ctf-int.h", which defines CTF kinds to be used internally to
represent BTF tags which must pass through the CTF container. It also
adds a new type for representing information specific to those tags, and
a member for that type in ctf_dtdef.

This patch also updates ctf_add_reftype to accept a const char * name,
and add it for the newly added type.

gcc/

* ctf-int.h: New file.
* ctfc.cc (ctf_add_reftype): Add NAME parameter. Pass it to
ctf_add_generic call.
(ctf_add_pointer): Update ctf_add_reftype call accordingly.
* ctfc.h (ctf_add_reftype): Analogous change.
(ctf_btf_annotation): New.
(ctf_dtdef): Add member for it.
(enum ctf_dtu_d_union_enum): Likewise.
* dwarf2ctf.cc (gen_ctf_modifier_type): Update call to
ctf_add_reftype accordingly.
---
 gcc/ctf-int.h| 29 +
 gcc/ctfc.cc  | 11 +++
 gcc/ctfc.h   | 17 ++---
 gcc/dwarf2ctf.cc |  2 +-
 4 files changed, 51 insertions(+), 8 deletions(-)
 create mode 100644 gcc/ctf-int.h

diff --git a/gcc/ctf-int.h b/gcc/ctf-int.h
new file mode 100644
index 000..fb5f4aacad6
--- /dev/null
+++ b/gcc/ctf-int.h
@@ -0,0 +1,29 @@
+/* ctf-int.h - GCC internal definitions used for CTF debug info.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_CTF_INT_H
+#define GCC_CTF_INT_H 1
+
+/* These CTF kinds only exist as a bridge to generating BTF types for
+   BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG. They do not correspond to any
+   representable type kind in CTF.  */
+#define CTF_K_DECL_TAG  62
+#define CTF_K_TYPE_TAG  63
+
+#endif /* GCC_CTF_INT_H */
diff --git a/gcc/ctfc.cc b/gcc/ctfc.cc
index f24e7bff948..a0404520b2a 100644
--- a/gcc/ctfc.cc
+++ b/gcc/ctfc.cc
@@ -107,6 +107,9 @@ ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype)
   return CTF_DTU_D_ARGUMENTS;
 case CTF_K_SLICE:
   return CTF_DTU_D_SLICE;
+case CTF_K_DECL_TAG:
+case CTF_K_TYPE_TAG:
+  return CTF_DTU_D_BTFNOTE;
 default:
   /* The largest member as default.  */
   return CTF_DTU_D_ARRAY;
@@ -428,15 +431,15 @@ ctf_add_encoded (ctf_container_ref ctfc, uint32_t flag, 
const char * name,
 }
 
 ctf_id_t
-ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
-uint32_t kind, dw_die_ref die)
+ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, const char * name,
+ctf_id_t ref, uint32_t kind, dw_die_ref die)
 {
   ctf_dtdef_ref dtd;
   ctf_id_t type;
 
   gcc_assert (ref <= CTF_MAX_TYPE);
 
-  type = ctf_add_generic (ctfc, flag, NULL, &dtd, die);
+  type = ctf_add_generic (ctfc, flag, name, &dtd, die);
   dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0);
   /* Caller of this API must guarantee that a CTF type with id = ref already
  exists.  This will also be validated for us at link-time.  */
@@ -548,7 +551,7 @@ ctf_id_t
 ctf_add_pointer (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
 dw_die_ref die)
 {
-  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_POINTER, die));
+  return (ctf_add_reftype (ctfc, flag, NULL, ref, CTF_K_POINTER, die));
 }
 
 ctf_id_t
diff --git a/gcc/ctfc.h b/gcc/ctfc.h
index 001e544ef08..fab18f024d7 100644
--- a/gcc/ctfc.h
+++ b/gcc/ctfc.h
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dwarf2ctf.h"
 #include "ctf.h"
 #include "btf.h"
+#include "ctf-int.h"
 
 /* Invalid CTF type ID definition.  */
 
@@ -151,6 +152,13 @@ typedef struct GTY (()) ctf_func_arg
 
 #define ctf_farg_list_next(elem) ((ctf_func_arg_t *)((elem)->farg_next))
 
+/* BTF support: a BTF type tag or decl tag.  */
+
+typedef struct GTY (()) ctf_btf_annotation
+{
+  uint32_t component_idx;
+} ctf_btf_annotation_t;
+
 /* Type definition for CTF generation.  */
 
 struct GTY ((for_user)) ctf_dtdef
@@ -173,6 +181,8 @@ struct GTY ((for_user)) ctf_dtdef
 ctf_func_arg_t * GTY ((tag ("CTF_DTU_D_ARGUMENTS"))) dtu_argv;
 /* slice.  */
 ctf_sliceinfo_t GTY ((tag ("CTF_DTU_D_SLICE"))) dtu_slice;
+/* btf annotation.  */
+ctf_btf_annotation_t GTY ((tag ("CTF_DTU_D_BTFNOTE"))) dtu_btfnote;
   } dtd_u;
 };
 
@@ -212,7 +222,8 @@ enum ctf_dtu_d_union

[PATCH 3/9] c-family: Add debug_annotate attribute handlers

2022-06-07 Thread David Faust via Gcc-patches
This patch adds attribute handlers for two new attributes:
"debug_annotate_decl" and "debug_annotate_type". Both attributes accept
a single string argument, and are used to add arbitrary annotations to
debug information generated for the decls or types to which they apply.

gcc/c-family/

* c-attribs.cc (c_common_attribute_table): Add new attributes
debug_annotate_decl and debug_annotate_type.
(handle_debug_annotate_decl_attribute): New.
(handle_debug_annotate_type_attribute): Likewise.
---
 gcc/c-family/c-attribs.cc | 43 +++
 1 file changed, 43 insertions(+)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index c8d96723f4c..50e8fc1b695 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -174,6 +174,9 @@ static tree handle_signed_bool_precision_attribute (tree *, 
tree, tree, int,
bool *);
 static tree handle_retain_attribute (tree *, tree, tree, int, bool *);
 
+static tree handle_debug_annotate_decl_attribute (tree *, tree, tree, int, 
bool *);
+static tree handle_debug_annotate_type_attribute (tree *, tree, tree, int, 
bool *);
+
 /* Helper to define attribute exclusions.  */
 #define ATTR_EXCL(name, function, type, variable)  \
   { name, function, type, variable }
@@ -555,6 +558,10 @@ const struct attribute_spec c_common_attribute_table[] =
  handle_dealloc_attribute, NULL },
   { "tainted_args",  0, 0, true,  false, false, false,
  handle_tainted_args_attribute, NULL },
+  { "debug_annotate_decl",1, 1, false, false, false, false,
+ handle_debug_annotate_decl_attribute, NULL },
+  { "debug_annotate_type",1, 1, false, true, false, false,
+ handle_debug_annotate_type_attribute, NULL },
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
 };
 
@@ -5868,6 +5875,42 @@ handle_tainted_args_attribute (tree *node, tree name, 
tree, int,
   return NULL_TREE;
 }
 
+/* Handle a "debug_annotate_decl" attribute; arguments as in
+   struct attribute_spec.handler.   */
+
+static tree
+handle_debug_annotate_decl_attribute (tree *, tree name, tree args, int,
+ bool *no_add_attrs)
+{
+  if (!args)
+*no_add_attrs = true;
+  else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+{
+  error ("%qE attribute requires a string", name);
+  *no_add_attrs = true;
+}
+
+  return NULL_TREE;
+}
+
+/* Handle a "debug_annotate_type" attribute; arguments as in
+   struct attribute_spec.handler.   */
+
+static tree
+handle_debug_annotate_type_attribute (tree *, tree name, tree args, int,
+ bool *no_add_attrs)
+{
+  if (!args)
+*no_add_attrs = true;
+  else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+{
+  error ("%qE attribute requires a string", name);
+  *no_add_attrs = true;
+}
+
+  return NULL_TREE;
+}
+
 /* Attempt to partially validate a single attribute ATTR as if
it were to be applied to an entity OPER.  */
 
-- 
2.36.1



[PATCH 2/9] include: Add new definitions

2022-06-07 Thread David Faust via Gcc-patches
include/

* btf.h: Add BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG defines. Update
comments.
(struct btf_decl_tag): New.
* dwarf2.def: Add new DWARF extension DW_TAG_GNU_annotation.
---
 include/btf.h  | 17 +++--
 include/dwarf2.def |  4 
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/include/btf.h b/include/btf.h
index 78b551ced23..37deaef8b48 100644
--- a/include/btf.h
+++ b/include/btf.h
@@ -69,7 +69,7 @@ struct btf_type
 
   /* SIZE is used by INT, ENUM, STRUCT, UNION, DATASEC kinds.
  TYPE is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, FUNC,
- FUNC_PROTO and VAR kinds.  */
+ FUNC_PROTO, VAR and DECL_TAG kinds.  */
   union
   {
 uint32_t size; /* Size of the entire type, in bytes.  */
@@ -109,7 +109,9 @@ struct btf_type
 #define BTF_KIND_VAR   14  /* Variable.  */
 #define BTF_KIND_DATASEC   15  /* Section such as .bss or .data.  */
 #define BTF_KIND_FLOAT 16  /* Floating point.  */
-#define BTF_KIND_MAX   BTF_KIND_FLOAT
+#define BTF_KIND_DECL_TAG  17  /* Decl Tag.  */
+#define BTF_KIND_TYPE_TAG  18  /* Type Tag.  */
+#define BTF_KIND_MAX   BTF_KIND_TYPE_TAG
 #define NR_BTF_KINDS   (BTF_KIND_MAX + 1)
 
 /* For some BTF_KINDs, struct btf_type is immediately followed by
@@ -190,6 +192,17 @@ struct btf_var_secinfo
   uint32_t size;   /* Size (in bytes) of variable.  */
 };
 
+/* BTF_KIND_DECL_TAG is followed by a single struct btf_decl_tag, which
+   describes the tag location:
+   - If component_idx == -1, then the tag is applied to a struct, union,
+ variable or function.
+   - Otherwise it is applied to a struct/union member or function argument
+ with the given given index numbered 0..vlen-1.  */
+struct btf_decl_tag
+{
+  int32_t component_idx;
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 530c6f849f9..a1f7a47a036 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -174,6 +174,10 @@ DW_TAG (DW_TAG_GNU_formal_parameter_pack, 0x4108)
are properly part of DWARF 5.  */
 DW_TAG (DW_TAG_GNU_call_site, 0x4109)
 DW_TAG (DW_TAG_GNU_call_site_parameter, 0x410a)
+
+/* Extension for BTF annotations.  */
+DW_TAG (DW_TAG_GNU_annotation, 0x6000)
+
 /* Extensions for UPC.  See: http://dwarfstd.org/doc/DWARF4.pdf.  */
 DW_TAG (DW_TAG_upc_shared_type, 0x8765)
 DW_TAG (DW_TAG_upc_strict_type, 0x8766)
-- 
2.36.1



[PATCH 0/9] Add debug_annotate attributes

2022-06-07 Thread David Faust via Gcc-patches
Hello,

This patch series adds support for:

- Two new C-language-level attributes that allow to associate (to "annotate" or
  to "tag") particular declarations and types with arbitrary strings. As
  explained below, this is intended to be used to, for example, characterize
  certain pointer types.

- The conveyance of that information in the DWARF output in the form of a new
  DIE: DW_TAG_GNU_annotation.

- The conveyance of that information in the BTF output in the form of two new
  kinds of BTF objects: BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG.

All of these facilities are being added to the eBPF ecosystem, and support for
them exists in some form in LLVM.

Purpose
===

1)  Addition of C-family language constructs (attributes) to specify free-text
tags on certain language elements, such as struct fields.

The purpose of these annotations is to provide additional information about
types, variables, and function parameters of interest to the kernel. A
driving use case is to tag pointer types within the linux kernel and eBPF
programs with additional semantic information, such as '__user' or '__rcu'.

For example, consider the linux kernel function do_execve with the
following declaration:

  static int do_execve(struct filename *filename,
 const char __user *const __user *__argv,
 const char __user *const __user *__envp);

Here, __user could be defined with these annotations to record semantic
information about the pointer parameters (e.g., they are user-provided) in
DWARF and BTF information. Other kernel facilites such as the eBPF verifier
can read the tags and make use of the information.

2)  Conveying the tags in the generated DWARF debug info.

The main motivation for emitting the tags in DWARF is that the Linux kernel
generates its BTF information via pahole, using DWARF as a source:

++  BTF  BTF   +--+
| pahole |---> vmlinux.btf --->| verifier |
++ +--+
^^
||
  DWARF |BTF |
||
 vmlinux  +-+
 module1.ko   | BPF program |
 module2.ko   +-+
   ...

This is because:

a)  Unlike GCC, LLVM will only generate BTF for BPF programs.

b)  GCC can generate BTF for whatever target with -gbtf, but there is no
support for linking/deduplicating BTF in the linker.

In the scenario above, the verifier needs access to the pointer tags of
both the kernel types/declarations (conveyed in the DWARF and translated
to BTF by pahole) and those of the BPF program (available directly in BTF).

Another motivation for having the tag information in DWARF, unrelated to
BPF and BTF, is that the drgn project (another DWARF consumer) also wants
to benefit from these tags in order to differentiate between different
kinds of pointers in the kernel.

3)  Conveying the tags in the generated BTF debug info.

This is easy: the main purpose of having this info in BTF is for the
compiled eBPF programs. The kernel verifier can then access the tags
of pointers used by the eBPF programs.


For more information about these tags and the motivation behind them, please
refer to the following linux kernel discussions:

  https://lore.kernel.org/bpf/20210914223004.244411-1-...@fb.com/
  https://lore.kernel.org/bpf/20211012164838.3345699-1-...@fb.com/
  https://lore.kernel.org/bpf/2022012604.1504583-1-...@fb.com/


Implementation Overview
===

To enable these annotations, two new C language attributes are added:
__attribute__((debug_annotate_decl("foo"))) and
__attribute__((debug_annotate_type("bar"))). Both attributes accept a single
arbitrary string constant argument, which will be recorded in the generated
DWARF and/or BTF debug information. They have no effect on code generation.

Note that we are not using the same attribute names as LLVM (btf_decl_tag and
btf_type_tag, respectively). While these attributes are functionally very
similar, they have grown beyond purely BTF-specific uses, so inclusion of "btf"
in the attribute name seems misleading.

DWARF support is enabled via a new DW_TAG_GNU_annotation. When generating DWARF,
declarations and types will be checked for the corresponding attributes. If
present, a DW_TAG_GNU_annotation DIE will be created as a child of the DIE for
the annotated type or declaration, one for each tag. These DIEs link the
arbitrary tag value to the item they annotate.

For example, the following variable declaration:

  #define __typetag1 __attribute__((debug_annotate_type ("typetag1")))

  #define __decltag1 __attribute__((debug_a

[PATCH 1/9] dwarf: add dw_get_die_parent function

2022-06-07 Thread David Faust via Gcc-patches
gcc/

* dwarf2out.cc (dw_get_die_parent): New function.
* dwarf2out.h (dw_get_die_parent): Declare it here.
---
 gcc/dwarf2out.cc | 8 
 gcc/dwarf2out.h  | 1 +
 2 files changed, 9 insertions(+)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 29f32ec6939..9c61026bb34 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -5235,6 +5235,14 @@ dw_get_die_sib (dw_die_ref die)
   return die->die_sib;
 }
 
+/* Return a reference to the parent of a given DIE.  */
+
+dw_die_ref
+dw_get_die_parent (dw_die_ref die)
+{
+  return die->die_parent;
+}
+
 /* Add an address constant attribute value to a DIE.  When using
dwarf_split_debug_info, address attributes in dies destined for the
final executable should be direct references--setting the parameter
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 656ef94afde..e6962fb4848 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -455,6 +455,7 @@ extern dw_die_ref lookup_type_die (tree);
 
 extern dw_die_ref dw_get_die_child (dw_die_ref);
 extern dw_die_ref dw_get_die_sib (dw_die_ref);
+extern dw_die_ref dw_get_die_parent (dw_die_ref);
 extern enum dwarf_tag dw_get_die_tag (dw_die_ref);
 
 /* Data about a single source file.  */
-- 
2.36.1



Re: [ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-06-07 Thread David Faust via Gcc-patches



On 6/2/22 19:04, Yonghong Song wrote:
> 
> 
> On 5/27/22 12:56 PM, David Faust wrote:
>>
>>
>> On 5/26/22 00:29, Yonghong Song wrote:
>>>
>>>
>>> On 5/24/22 10:04 AM, David Faust wrote:
>>>>
>>>>
>>>> On 5/24/22 09:03, Yonghong Song wrote:
>>>>>
>>>>>
>>>>> On 5/24/22 8:53 AM, David Faust wrote:
>>>>>>
>>>>>>
>>>>>> On 5/24/22 04:07, Jose E. Marchesi wrote:
>>>>>>>
>>>>>>>> On 5/11/22 11:44 AM, David Faust wrote:
>>>>>>>>>
>>>>>>>>> On 5/10/22 22:05, Yonghong Song wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 5/10/22 8:43 PM, Yonghong Song wrote:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 5/6/22 2:18 PM, David Faust wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On 5/5/22 16:00, Yonghong Song wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 5/4/22 10:03 AM, David Faust wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On 5/3/22 15:32, Joseph Myers wrote:
>>>>>>>>>>>>>>> On Mon, 2 May 2022, David Faust via Gcc-patches wrote:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> Consider the following example:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>  #define __typetag1 
>>>>>>>>>>>>>>>> __attribute__((btf_type_tag("tag1")))
>>>>>>>>>>>>>>>>  #define __typetag2 
>>>>>>>>>>>>>>>> __attribute__((btf_type_tag("tag2")))
>>>>>>>>>>>>>>>>  #define __typetag3 
>>>>>>>>>>>>>>>> __attribute__((btf_type_tag("tag3")))
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>  int __typetag1 * __typetag2 __typetag3 * g;
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> The expected behavior is that 'g' is "a pointer with tags
>>>>>>>>>>>>>>>> 'tag2' and
>>>>>>>>>>>>>>>> 'tag3',
>>>>>>>>>>>>>>>> to a pointer with tag 'tag1' to an int". i.e.:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> That's not a correct expectation for either GNU __attribute__ or
>>>>>>>>>>>>>>> C2x [[]]
>>>>>>>>>>>>>>> attribute syntax.  In either syntax, __typetag2 __typetag3 
>>>>>>>>>>>>>>> should
>>>>>>>>>>>>>>> apply to
>>>>>>>>>>>>>>> the type to which g points, not to g or its type, just as if
>>>>>>>>>>>>>>> you had a
>>>>>>>>>>>>>>> type qualifier there.  You'd need to put the attributes (or
>>>>>>>>>>>>>>> qualifier)
>>>>>>>>>>>>>>> after the *, not before, to make them apply to the pointer
>>>>>>>>>>>>>>> type.  See
>>>>>>>>>>>>>>> "Attribute Syntax" in the GCC manual for how the syntax is
>>>>>>>>>>>>>>> defined for
>>>>>>>>>>>>>>> GNU
>>>>>>>>>>>>>>> attributes and deduce in turn, for each subsequence of the 
>>>>>>>>>>>>>>> tokens
>>>>>>>>>>>>>>> matching
>>>>>>>&g

Re: [ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-05-27 Thread David Faust via Gcc-patches



On 5/26/22 00:29, Yonghong Song wrote:
> 
> 
> On 5/24/22 10:04 AM, David Faust wrote:
>>
>>
>> On 5/24/22 09:03, Yonghong Song wrote:
>>>
>>>
>>> On 5/24/22 8:53 AM, David Faust wrote:
>>>>
>>>>
>>>> On 5/24/22 04:07, Jose E. Marchesi wrote:
>>>>>
>>>>>> On 5/11/22 11:44 AM, David Faust wrote:
>>>>>>>
>>>>>>> On 5/10/22 22:05, Yonghong Song wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 5/10/22 8:43 PM, Yonghong Song wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 5/6/22 2:18 PM, David Faust wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 5/5/22 16:00, Yonghong Song wrote:
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> On 5/4/22 10:03 AM, David Faust wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> On 5/3/22 15:32, Joseph Myers wrote:
>>>>>>>>>>>>> On Mon, 2 May 2022, David Faust via Gcc-patches wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Consider the following example:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     #define __typetag1 __attribute__((btf_type_tag("tag1")))
>>>>>>>>>>>>>>     #define __typetag2 __attribute__((btf_type_tag("tag2")))
>>>>>>>>>>>>>>     #define __typetag3 __attribute__((btf_type_tag("tag3")))
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>     int __typetag1 * __typetag2 __typetag3 * g;
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> The expected behavior is that 'g' is "a pointer with tags
>>>>>>>>>>>>>> 'tag2' and
>>>>>>>>>>>>>> 'tag3',
>>>>>>>>>>>>>> to a pointer with tag 'tag1' to an int". i.e.:
>>>>>>>>>>>>>
>>>>>>>>>>>>> That's not a correct expectation for either GNU __attribute__ or
>>>>>>>>>>>>> C2x [[]]
>>>>>>>>>>>>> attribute syntax.  In either syntax, __typetag2 __typetag3 should
>>>>>>>>>>>>> apply to
>>>>>>>>>>>>> the type to which g points, not to g or its type, just as if
>>>>>>>>>>>>> you had a
>>>>>>>>>>>>> type qualifier there.  You'd need to put the attributes (or
>>>>>>>>>>>>> qualifier)
>>>>>>>>>>>>> after the *, not before, to make them apply to the pointer
>>>>>>>>>>>>> type.  See
>>>>>>>>>>>>> "Attribute Syntax" in the GCC manual for how the syntax is
>>>>>>>>>>>>> defined for
>>>>>>>>>>>>> GNU
>>>>>>>>>>>>> attributes and deduce in turn, for each subsequence of the tokens
>>>>>>>>>>>>> matching
>>>>>>>>>>>>> the syntax for some kind of declarator, what the type for "T D1"
>>>>>>>>>>>>> would be
>>>>>>>>>>>>> as defined there and in the C standard, as deduced from the type 
>>>>>>>>>>>>> for
>>>>>>>>>>>>> "T D"
>>>>>>>>>>>>> for a sub-declarator D.
>>>>>>>>>>>>>      >> But GCC's attribute parsing produces a variable 'g'
>>>>>>>>>>>>> which is "a
>>>>>>>>>>>> pointer with
>>>>>>>>>>>>>> tag 'tag1' to a pointer with tags 'tag2' and 'tag3' to an
>>>>>>>&

Re: [ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-05-24 Thread David Faust via Gcc-patches



On 5/24/22 09:03, Yonghong Song wrote:
> 
> 
> On 5/24/22 8:53 AM, David Faust wrote:
>>
>>
>> On 5/24/22 04:07, Jose E. Marchesi wrote:
>>>
>>>> On 5/11/22 11:44 AM, David Faust wrote:
>>>>>
>>>>> On 5/10/22 22:05, Yonghong Song wrote:
>>>>>>
>>>>>>
>>>>>> On 5/10/22 8:43 PM, Yonghong Song wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 5/6/22 2:18 PM, David Faust wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 5/5/22 16:00, Yonghong Song wrote:
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> On 5/4/22 10:03 AM, David Faust wrote:
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> On 5/3/22 15:32, Joseph Myers wrote:
>>>>>>>>>>> On Mon, 2 May 2022, David Faust via Gcc-patches wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Consider the following example:
>>>>>>>>>>>>
>>>>>>>>>>>>    #define __typetag1 __attribute__((btf_type_tag("tag1")))
>>>>>>>>>>>>    #define __typetag2 __attribute__((btf_type_tag("tag2")))
>>>>>>>>>>>>    #define __typetag3 __attribute__((btf_type_tag("tag3")))
>>>>>>>>>>>>
>>>>>>>>>>>>    int __typetag1 * __typetag2 __typetag3 * g;
>>>>>>>>>>>>
>>>>>>>>>>>> The expected behavior is that 'g' is "a pointer with tags
>>>>>>>>>>>> 'tag2' and
>>>>>>>>>>>> 'tag3',
>>>>>>>>>>>> to a pointer with tag 'tag1' to an int". i.e.:
>>>>>>>>>>>
>>>>>>>>>>> That's not a correct expectation for either GNU __attribute__ or
>>>>>>>>>>> C2x [[]]
>>>>>>>>>>> attribute syntax.  In either syntax, __typetag2 __typetag3 should
>>>>>>>>>>> apply to
>>>>>>>>>>> the type to which g points, not to g or its type, just as if
>>>>>>>>>>> you had a
>>>>>>>>>>> type qualifier there.  You'd need to put the attributes (or
>>>>>>>>>>> qualifier)
>>>>>>>>>>> after the *, not before, to make them apply to the pointer
>>>>>>>>>>> type.  See
>>>>>>>>>>> "Attribute Syntax" in the GCC manual for how the syntax is
>>>>>>>>>>> defined for
>>>>>>>>>>> GNU
>>>>>>>>>>> attributes and deduce in turn, for each subsequence of the tokens
>>>>>>>>>>> matching
>>>>>>>>>>> the syntax for some kind of declarator, what the type for "T D1"
>>>>>>>>>>> would be
>>>>>>>>>>> as defined there and in the C standard, as deduced from the type for
>>>>>>>>>>> "T D"
>>>>>>>>>>> for a sub-declarator D.
>>>>>>>>>>>     >> But GCC's attribute parsing produces a variable 'g'
>>>>>>>>>>> which is "a
>>>>>>>>>> pointer with
>>>>>>>>>>>> tag 'tag1' to a pointer with tags 'tag2' and 'tag3' to an
>>>>>>>>>>>> int", i.e.
>>>>>>>>>>>
>>>>>>>>>>> In GNU syntax, __typetag1 applies to the declaration, whereas in C2x
>>>>>>>>>>> syntax it applies to int.  Again, if you wanted it to apply to the
>>>>>>>>>>> pointer
>>>>>>>>>>> type it would need to go after the * not before.
>>>>>>>>>>>
>>>>>>>>>>> If you are concerned with the fine details of what construct an
>>>>>>>>>>> attribute
>>>>>>>>>>&

Re: [ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-05-24 Thread David Faust via Gcc-patches



On 5/24/22 04:07, Jose E. Marchesi wrote:
> 
>> On 5/11/22 11:44 AM, David Faust wrote:
>>>
>>> On 5/10/22 22:05, Yonghong Song wrote:
>>>>
>>>>
>>>> On 5/10/22 8:43 PM, Yonghong Song wrote:
>>>>>
>>>>>
>>>>> On 5/6/22 2:18 PM, David Faust wrote:
>>>>>>
>>>>>>
>>>>>> On 5/5/22 16:00, Yonghong Song wrote:
>>>>>>>
>>>>>>>
>>>>>>> On 5/4/22 10:03 AM, David Faust wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 5/3/22 15:32, Joseph Myers wrote:
>>>>>>>>> On Mon, 2 May 2022, David Faust via Gcc-patches wrote:
>>>>>>>>>
>>>>>>>>>> Consider the following example:
>>>>>>>>>>
>>>>>>>>>>   #define __typetag1 __attribute__((btf_type_tag("tag1")))
>>>>>>>>>>   #define __typetag2 __attribute__((btf_type_tag("tag2")))
>>>>>>>>>>   #define __typetag3 __attribute__((btf_type_tag("tag3")))
>>>>>>>>>>
>>>>>>>>>>   int __typetag1 * __typetag2 __typetag3 * g;
>>>>>>>>>>
>>>>>>>>>> The expected behavior is that 'g' is "a pointer with tags
>>>>>>>>>> 'tag2' and
>>>>>>>>>> 'tag3',
>>>>>>>>>> to a pointer with tag 'tag1' to an int". i.e.:
>>>>>>>>>
>>>>>>>>> That's not a correct expectation for either GNU __attribute__ or
>>>>>>>>> C2x [[]]
>>>>>>>>> attribute syntax.  In either syntax, __typetag2 __typetag3 should
>>>>>>>>> apply to
>>>>>>>>> the type to which g points, not to g or its type, just as if
>>>>>>>>> you had a
>>>>>>>>> type qualifier there.  You'd need to put the attributes (or
>>>>>>>>> qualifier)
>>>>>>>>> after the *, not before, to make them apply to the pointer
>>>>>>>>> type.  See
>>>>>>>>> "Attribute Syntax" in the GCC manual for how the syntax is
>>>>>>>>> defined for
>>>>>>>>> GNU
>>>>>>>>> attributes and deduce in turn, for each subsequence of the tokens
>>>>>>>>> matching
>>>>>>>>> the syntax for some kind of declarator, what the type for "T D1"
>>>>>>>>> would be
>>>>>>>>> as defined there and in the C standard, as deduced from the type for
>>>>>>>>> "T D"
>>>>>>>>> for a sub-declarator D.
>>>>>>>>>    >> But GCC's attribute parsing produces a variable 'g'
>>>>>>>>> which is "a
>>>>>>>> pointer with
>>>>>>>>>> tag 'tag1' to a pointer with tags 'tag2' and 'tag3' to an
>>>>>>>>>> int", i.e.
>>>>>>>>>
>>>>>>>>> In GNU syntax, __typetag1 applies to the declaration, whereas in C2x
>>>>>>>>> syntax it applies to int.  Again, if you wanted it to apply to the
>>>>>>>>> pointer
>>>>>>>>> type it would need to go after the * not before.
>>>>>>>>>
>>>>>>>>> If you are concerned with the fine details of what construct an
>>>>>>>>> attribute
>>>>>>>>> appertains to, I recommend using C2x syntax not GNU syntax.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Joseph, thank you! This is very helpful. My understanding of
>>>>>>>> the syntax
>>>>>>>> was not correct.
>>>>>>>>
>>>>>>>> (Actually, I made a bad mistake in paraphrasing this example from the
>>>>>>>> discussion of it in the series cover letter. But, the reason
>>>>>>>> why it is
>>>>>>>> incorrect is the same.)
>>>>

Re: [ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-05-11 Thread David Faust via Gcc-patches




On 5/10/22 22:05, Yonghong Song wrote:



On 5/10/22 8:43 PM, Yonghong Song wrote:



On 5/6/22 2:18 PM, David Faust wrote:



On 5/5/22 16:00, Yonghong Song wrote:



On 5/4/22 10:03 AM, David Faust wrote:



On 5/3/22 15:32, Joseph Myers wrote:

On Mon, 2 May 2022, David Faust via Gcc-patches wrote:


Consider the following example:

  #define __typetag1 __attribute__((btf_type_tag("tag1")))
  #define __typetag2 __attribute__((btf_type_tag("tag2")))
  #define __typetag3 __attribute__((btf_type_tag("tag3")))

  int __typetag1 * __typetag2 __typetag3 * g;

The expected behavior is that 'g' is "a pointer with tags 'tag2' and
'tag3',
to a pointer with tag 'tag1' to an int". i.e.:


That's not a correct expectation for either GNU __attribute__ or
C2x [[]]
attribute syntax.  In either syntax, __typetag2 __typetag3 should
apply to
the type to which g points, not to g or its type, just as if you had a
type qualifier there.  You'd need to put the attributes (or qualifier)
after the *, not before, to make them apply to the pointer type.  See
"Attribute Syntax" in the GCC manual for how the syntax is defined for
GNU
attributes and deduce in turn, for each subsequence of the tokens
matching
the syntax for some kind of declarator, what the type for "T D1"
would be
as defined there and in the C standard, as deduced from the type for
"T D"
for a sub-declarator D.
   >> But GCC's attribute parsing produces a variable 'g' which is "a

pointer with

tag 'tag1' to a pointer with tags 'tag2' and 'tag3' to an int", i.e.


In GNU syntax, __typetag1 applies to the declaration, whereas in C2x
syntax it applies to int.  Again, if you wanted it to apply to the
pointer
type it would need to go after the * not before.

If you are concerned with the fine details of what construct an
attribute
appertains to, I recommend using C2x syntax not GNU syntax.



Joseph, thank you! This is very helpful. My understanding of the syntax
was not correct.

(Actually, I made a bad mistake in paraphrasing this example from the
discussion of it in the series cover letter. But, the reason why it is
incorrect is the same.)


Yonghong, is the specific ordering an expectation in BPF programs or
other users of the tags?


This is probably a language writing issue. We are saying tags only
apply to pointer. We probably should say it only apply to pointee.

$ cat t.c
int const *ptr;

the llvm ir debuginfo:

!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
!6 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !7)
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)

We could replace 'const' with a tag like below:

int __attribute__((btf_type_tag("tag"))) *ptr;

!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64,
annotations: !7)
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!7 = !{!8}
!8 = !{!"btf_type_tag", !"tag"}

In the above IR, we generate annotations to pointer_type because
we didn't invent a new DI type for encode btf_type_tag. But it is
totally okay to have IR looks like

!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
!11 = !DIBtfTypeTagType(..., baseType: !6, name: !"Tag")
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)


OK, thanks.

There is still the question of why the DWARF generated for this case
that I have been concerned about:

    int __typetag1 * __typetag2 __typetag3 * g;

differs between GCC (with this series) and clang. After studying it,
GCC is doing with the attributes exactly as is described in the
Attribute Syntax portion of the GCC manual where the GNU syntax is
described. I do not think there is any problem here.

So the difference in DWARF suggests to me that clang is not handling
the GNU attribute syntax in this particular case correctly, since it
seems to be associating __typetag2 and __typetag3 to g's type rather
than the type to which it points.

I am not sure whether for the use purposes of the tags this difference
is very important, but it is worth noting.


As Joseph suggested, it may be better to encourage users of these tags
to use the C2x attribute syntax if they are concerned with precisely
which construct the tag applies.

This would also be a way around any issues in handling the attributes
due to the GNU syntax.

I tried a few test cases using C2x syntax BTF type tags with a
clang-15 build, but ran into some issues (in particular, some of the
tag attributes being ignored altogether). I couldn't find confirmation
whether C2x attribute syntax is fully supported in clang yet, so maybe
this isn't expected to work. Do you know whether the C2x syntax is
fully supported in clang yet?


Actually, I don'

Re: [ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-05-06 Thread David Faust via Gcc-patches




On 5/5/22 16:00, Yonghong Song wrote:



On 5/4/22 10:03 AM, David Faust wrote:



On 5/3/22 15:32, Joseph Myers wrote:

On Mon, 2 May 2022, David Faust via Gcc-patches wrote:


Consider the following example:

     #define __typetag1 __attribute__((btf_type_tag("tag1")))
     #define __typetag2 __attribute__((btf_type_tag("tag2")))
     #define __typetag3 __attribute__((btf_type_tag("tag3")))

     int __typetag1 * __typetag2 __typetag3 * g;

The expected behavior is that 'g' is "a pointer with tags 'tag2' and
'tag3',
to a pointer with tag 'tag1' to an int". i.e.:


That's not a correct expectation for either GNU __attribute__ or C2x [[]]
attribute syntax.  In either syntax, __typetag2 __typetag3 should
apply to
the type to which g points, not to g or its type, just as if you had a
type qualifier there.  You'd need to put the attributes (or qualifier)
after the *, not before, to make them apply to the pointer type.  See
"Attribute Syntax" in the GCC manual for how the syntax is defined for
GNU
attributes and deduce in turn, for each subsequence of the tokens
matching
the syntax for some kind of declarator, what the type for "T D1" would be
as defined there and in the C standard, as deduced from the type for
"T D"
for a sub-declarator D.
  >> But GCC's attribute parsing produces a variable 'g' which is "a

pointer with

tag 'tag1' to a pointer with tags 'tag2' and 'tag3' to an int", i.e.


In GNU syntax, __typetag1 applies to the declaration, whereas in C2x
syntax it applies to int.  Again, if you wanted it to apply to the
pointer
type it would need to go after the * not before.

If you are concerned with the fine details of what construct an attribute
appertains to, I recommend using C2x syntax not GNU syntax.



Joseph, thank you! This is very helpful. My understanding of the syntax
was not correct.

(Actually, I made a bad mistake in paraphrasing this example from the
discussion of it in the series cover letter. But, the reason why it is
incorrect is the same.)


Yonghong, is the specific ordering an expectation in BPF programs or
other users of the tags?


This is probably a language writing issue. We are saying tags only
apply to pointer. We probably should say it only apply to pointee.

$ cat t.c
int const *ptr;

the llvm ir debuginfo:

!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64)
!6 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !7)
!7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)

We could replace 'const' with a tag like below:

int __attribute__((btf_type_tag("tag"))) *ptr;

!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !6, size: 64,
annotations: !7)
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!7 = !{!8}
!8 = !{!"btf_type_tag", !"tag"}

In the above IR, we generate annotations to pointer_type because
we didn't invent a new DI type for encode btf_type_tag. But it is
totally okay to have IR looks like

!5 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
!11 = !DIBtfTypeTagType(..., baseType: !6, name: !"Tag")
!6 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)


OK, thanks.

There is still the question of why the DWARF generated for this case 
that I have been concerned about:


  int __typetag1 * __typetag2 __typetag3 * g;

differs between GCC (with this series) and clang. After studying it, GCC 
is doing with the attributes exactly as is described in the Attribute 
Syntax portion of the GCC manual where the GNU syntax is described. I do 
not think there is any problem here.


So the difference in DWARF suggests to me that clang is not handling the 
GNU attribute syntax in this particular case correctly, since it seems 
to be associating __typetag2 and __typetag3 to g's type rather than the 
type to which it points.


I am not sure whether for the use purposes of the tags this difference 
is very important, but it is worth noting.



As Joseph suggested, it may be better to encourage users of these tags 
to use the C2x attribute syntax if they are concerned with precisely 
which construct the tag applies.


This would also be a way around any issues in handling the attributes 
due to the GNU syntax.


I tried a few test cases using C2x syntax BTF type tags with a clang-15 
build, but ran into some issues (in particular, some of the tag 
attributes being ignored altogether). I couldn't find confirmation 
whether C2x attribute syntax is fully supported in clang yet, so maybe 
this isn't expected to work. Do you know whether the C2x syntax is fully 
supported in clang yet?






This example comes from my testing against clang to check that the BTF
generated by both toolchains is compatible. In this case we

Re: [ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-05-04 Thread David Faust via Gcc-patches




On 5/3/22 15:32, Joseph Myers wrote:

On Mon, 2 May 2022, David Faust via Gcc-patches wrote:


Consider the following example:

#define __typetag1 __attribute__((btf_type_tag("tag1")))
#define __typetag2 __attribute__((btf_type_tag("tag2")))
#define __typetag3 __attribute__((btf_type_tag("tag3")))

int __typetag1 * __typetag2 __typetag3 * g;

The expected behavior is that 'g' is "a pointer with tags 'tag2' and 'tag3',
to a pointer with tag 'tag1' to an int". i.e.:


That's not a correct expectation for either GNU __attribute__ or C2x [[]]
attribute syntax.  In either syntax, __typetag2 __typetag3 should apply to
the type to which g points, not to g or its type, just as if you had a
type qualifier there.  You'd need to put the attributes (or qualifier)
after the *, not before, to make them apply to the pointer type.  See
"Attribute Syntax" in the GCC manual for how the syntax is defined for GNU
attributes and deduce in turn, for each subsequence of the tokens matching
the syntax for some kind of declarator, what the type for "T D1" would be
as defined there and in the C standard, as deduced from the type for "T D"
for a sub-declarator D.
 >> But GCC's attribute parsing produces a variable 'g' which is "a 

pointer with

tag 'tag1' to a pointer with tags 'tag2' and 'tag3' to an int", i.e.


In GNU syntax, __typetag1 applies to the declaration, whereas in C2x
syntax it applies to int.  Again, if you wanted it to apply to the pointer
type it would need to go after the * not before.

If you are concerned with the fine details of what construct an attribute
appertains to, I recommend using C2x syntax not GNU syntax.



Joseph, thank you! This is very helpful. My understanding of the syntax 
was not correct.


(Actually, I made a bad mistake in paraphrasing this example from the 
discussion of it in the series cover letter. But, the reason why it is 
incorrect is the same.)



Yonghong, is the specific ordering an expectation in BPF programs or 
other users of the tags?


This example comes from my testing against clang to check that the BTF 
generated by both toolchains is compatible. In this case we get 
different results when using the GNU attribute syntax.



To avoid confusion, here is the full example (from the cover letter). 
The difference in the results is clear in the DWARF.



Consider the following example:

  #define __typetag1 __attribute__((btf_type_tag("type-tag-1")))
  #define __typetag2 __attribute__((btf_type_tag("type-tag-2")))
  #define __typetag3 __attribute__((btf_type_tag("type-tag-3")))

  int __typetag1 * __typetag2 __typetag3 * g;

 
asm_written unsigned DI
size 
unit-size 
align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 
0x77450888
attributes 
value 
readonly constant static "type-tag-3\000">>
chain 
value 
readonly constant static "type-tag-2\000">>>>
pointer_to_this >
asm_written unsigned DI size  unit-size 

align:64 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 
0x77509930
attributes 
value 
readonly constant static "type-tag-1\000">>>>
public static unsigned DI defer-output /home/dfaust/playpen/btf/annotate.c:29:42 size 
 unit-size 
align:64 warn_if_not_align:0>




The current implementation produces the following DWARF:

 <1><1e>: Abbrev Number: 4 (DW_TAG_variable)
<1f>   DW_AT_name: g
<21>   DW_AT_decl_file   : 1
<22>   DW_AT_decl_line   : 6
<23>   DW_AT_decl_column : 42
<24>   DW_AT_type: <0x32>
<28>   DW_AT_external: 1
<28>   DW_AT_location: 9 byte block: 3 0 0 0 0 0 0 0 0(DW_OP_addr: 
0)
 <1><32>: Abbrev Number: 2 (DW_TAG_pointer_type)
<33>   DW_AT_byte_size   : 8
<33>   DW_AT_type: <0x45>
<37>   DW_AT_sibling : <0x45>
 <2><3b>: Abbrev Number: 1 (User TAG value: 0x6000)
<3c>   DW_AT_name: (indirect string, offset: 0x18): btf_type_tag
<40>   DW_AT_const_value : (indirect string, offset: 0xc7): type-tag-1
 <2><44>: Abbrev Number: 0
 <1><45>: Abbrev Number: 2 (DW_TAG_pointer_type)
<46>   DW_AT_byte_size   : 8
<46>   DW_AT_type: <0x61>
<4a>   DW_AT_sibling : <0x61>
 <2><4e>: Abbrev Number: 1 (User TAG value: 0x6000)
<4f>   DW_AT_name: (indirect string, offset: 0x18): btf_type_tag
<53

[ping2][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-05-02 Thread David Faust via Gcc-patches

Pinging this series again.
Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-April/592685.html

This series adds new C-family frontend attributes for recording string 
"tags" in DWARF and BTF debug info to support kernel use cases.


There remains one issue in the implementation which has not been 
resolved, which I hope someone in the GCC community may be able to shed 
some light on.


Specifically, it is related to how GCC parses the attributes: In cases 
where the new btf_type_tag attribute (which applies to types) is 
specified multiple times on different intermediate pointer types of a 
declaration, GCC seems to attach the attributes to the TREEs in an 
unexpected order.


As a result the behavior of the attribute in GCC cannot be reconciled 
with its definition in BTF or behavior in the clang compiler.


Consider the following example:

   #define __typetag1 __attribute__((btf_type_tag("tag1")))
   #define __typetag2 __attribute__((btf_type_tag("tag2")))
   #define __typetag3 __attribute__((btf_type_tag("tag3")))

   int __typetag1 * __typetag2 __typetag3 * g;

The expected behavior is that 'g' is "a pointer with tags 'tag2' and 
'tag3', to a pointer with tag 'tag1' to an int". i.e.:


  
  
>>>

But GCC's attribute parsing produces a variable 'g' which is "a pointer 
with tag 'tag1' to a pointer with tags 'tag2' and 'tag3' to an int", i.e.


  
  
>>>

And as a result the DWARF and BTF generated for cases like this do not 
agree with the BTF type tag specification nor output of the clang 
compiler, which already supports this feature.


(Please refer to the "Current issues in implementation" section in the 
series cover letter for the full details of this example.)


So far I have been unable to resolve this issue in the btf_type_tag 
attribute handler. It seems to me that the cause must be "higher up" in 
the C frontend attribute parsing but I am not familiar with this area of 
GCC.


Any insight into understanding this issue or comments elsewhere in the 
series would be most welcome.


Thanks,
David

On 4/18/22 12:36, David Faust via Gcc-patches wrote:

Gentle ping :)

Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-April/592685.html

The series adds support for new attribues btf_type_tag and btf_decl_tag,
for recording arbitrary string tags in DWARF and BTF debug info. The
feature is to support kernel use cases.

Thanks,
David

On 4/1/22 12:42, David Faust via Gcc-patches wrote:

Hello,

This patch series is a first attempt at adding support for:

- Two new C-language-level attributes that allow to associate (to "tag")
particular declarations and types with arbitrary strings. As explained 
below,
this is intended to be used to, for example, characterize certain pointer
types.

- The conveyance of that information in the DWARF output in the form of a new
DIE: DW_TAG_GNU_annotation.

- The conveyance of that information in the BTF output in the form of two new
kinds of BTF objects: BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG.

All of these facilities are being added to the eBPF ecosystem, and support for
them exists in some form in LLVM. However, as we shall see, we have found some
problems implementing them so some discussion is in order.

Purpose
===

1)  Addition of C-family language constructs (attributes) to specify free-text
  tags on certain language elements, such as struct fields.

  The purpose of these annotations is to provide additional information 
about
  types, variables, and function paratemeters of interest to the kernel. A
  driving use case is to tag pointer types within the linux kernel and eBPF
  programs with additional semantic information, such as '__user' or 
'__rcu'.

  For example, consider the linux kernel function do_execve with the
  following declaration:

static int do_execve(struct filename *filename,
   const char __user *const __user *__argv,
   const char __user *const __user *__envp);

  Here, __user could be defined with these annotations to record semantic
  information about the pointer parameters (e.g., they are user-provided) in
  DWARF and BTF information. Other kernel facilites such as the eBPF 
verifier
  can read the tags and make use of the information.

2)  Conveying the tags in the generated DWARF debug info.

  The main motivation for emitting the tags in DWARF is that the Linux 
kernel
  generates its BTF information via pahole, using DWARF as a source:

  ++  BTF  BTF   +--+
  | pahole |---> vmlinux.btf --->| verifier |
  ++ +--+
  ^

[ping][PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-04-18 Thread David Faust via Gcc-patches

Gentle ping :)

Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-April/592685.html

The series adds support for new attribues btf_type_tag and btf_decl_tag, 
for recording arbitrary string tags in DWARF and BTF debug info. The 
feature is to support kernel use cases.


Thanks,
David

On 4/1/22 12:42, David Faust via Gcc-patches wrote:

Hello,

This patch series is a first attempt at adding support for:

- Two new C-language-level attributes that allow to associate (to "tag")
   particular declarations and types with arbitrary strings. As explained below,
   this is intended to be used to, for example, characterize certain pointer
   types.

- The conveyance of that information in the DWARF output in the form of a new
   DIE: DW_TAG_GNU_annotation.

- The conveyance of that information in the BTF output in the form of two new
   kinds of BTF objects: BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG.

All of these facilities are being added to the eBPF ecosystem, and support for
them exists in some form in LLVM. However, as we shall see, we have found some
problems implementing them so some discussion is in order.

Purpose
===

1)  Addition of C-family language constructs (attributes) to specify free-text
 tags on certain language elements, such as struct fields.

 The purpose of these annotations is to provide additional information about
 types, variables, and function paratemeters of interest to the kernel. A
 driving use case is to tag pointer types within the linux kernel and eBPF
 programs with additional semantic information, such as '__user' or '__rcu'.

 For example, consider the linux kernel function do_execve with the
 following declaration:

   static int do_execve(struct filename *filename,
  const char __user *const __user *__argv,
  const char __user *const __user *__envp);

 Here, __user could be defined with these annotations to record semantic
 information about the pointer parameters (e.g., they are user-provided) in
 DWARF and BTF information. Other kernel facilites such as the eBPF verifier
 can read the tags and make use of the information.

2)  Conveying the tags in the generated DWARF debug info.

 The main motivation for emitting the tags in DWARF is that the Linux kernel
 generates its BTF information via pahole, using DWARF as a source:

 ++  BTF  BTF   +--+
 | pahole |---> vmlinux.btf --->| verifier |
 ++ +--+
 ^^
 ||
   DWARF |BTF |
 ||
  vmlinux  +-+
  module1.ko   | BPF program |
  module2.ko   +-+
...

 This is because:

 a)  Unlike GCC, LLVM will only generate BTF for BPF programs.

 b)  GCC can generate BTF for whatever target with -gbtf, but there is no
 support for linking/deduplicating BTF in the linker.

 In the scenario above, the verifier needs access to the pointer tags of
 both the kernel types/declarations (conveyed in the DWARF and translated
 to BTF by pahole) and those of the BPF program (available directly in BTF).

 Another motivation for having the tag information in DWARF, unrelated to
 BPF and BTF, is that the drgn project (another DWARF consumer) also wants
 to benefit from these tags in order to differentiate between different
 kinds of pointers in the kernel.

3)  Conveying the tags in the generated BTF debug info.

 This is easy: the main purpose of having this info in BTF is for the
 compiled eBPF programs. The kernel verifier can then access the tags
 of pointers used by the eBPF programs.


For more information about these tags and the motivation behind them, please
refer to the following linux kernel discussions:

   https://lore.kernel.org/bpf/20210914223004.244411-1-...@fb.com/
   https://lore.kernel.org/bpf/20211012164838.3345699-1-...@fb.com/
   https://lore.kernel.org/bpf/2022012604.1504583-1-...@fb.com/


What is in this patch series


This patch series adds support for these annotations in GCC. The implementation
is largely complete. However, in some cases the produced debug info (both DWARF
and BTF) differs significantly from that produced by LLVM. This issue is
discussed in detail below, along with a few specific questions for both GCC and
LLVM. Any input would be much appreciated.


Implementation Overview
===

To enable these annotations, two new C language attributes are added:
__attribute__((btf_decl_tag("foo")) and __attribute__((btf_type_tag("bar"))).
Both attri

Re: [PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-04-05 Thread David Faust via Gcc-patches




On 4/4/22 15:13, Yonghong Song wrote:



On 4/1/22 12:42 PM, David Faust wrote:

Hello,

This patch series is a first attempt at adding support for:

- Two new C-language-level attributes that allow to associate (to "tag")
particular declarations and types with arbitrary strings. As explained 
below,
this is intended to be used to, for example, characterize certain pointer
types.

- The conveyance of that information in the DWARF output in the form of a new
DIE: DW_TAG_GNU_annotation.

- The conveyance of that information in the BTF output in the form of two new
kinds of BTF objects: BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG.

All of these facilities are being added to the eBPF ecosystem, and support for
them exists in some form in LLVM. However, as we shall see, we have found some
problems implementing them so some discussion is in order.

Purpose
===

1)  Addition of C-family language constructs (attributes) to specify free-text
  tags on certain language elements, such as struct fields.

  The purpose of these annotations is to provide additional information 
about
  types, variables, and function paratemeters of interest to the kernel. A
  driving use case is to tag pointer types within the linux kernel and eBPF
  programs with additional semantic information, such as '__user' or 
'__rcu'.

  For example, consider the linux kernel function do_execve with the
  following declaration:

static int do_execve(struct filename *filename,
   const char __user *const __user *__argv,
   const char __user *const __user *__envp);

  Here, __user could be defined with these annotations to record semantic
  information about the pointer parameters (e.g., they are user-provided) in
  DWARF and BTF information. Other kernel facilites such as the eBPF 
verifier
  can read the tags and make use of the information.

2)  Conveying the tags in the generated DWARF debug info.

  The main motivation for emitting the tags in DWARF is that the Linux 
kernel
  generates its BTF information via pahole, using DWARF as a source:

  ++  BTF  BTF   +--+
  | pahole |---> vmlinux.btf --->| verifier |
  ++ +--+
  ^^
  ||
DWARF |BTF |
  ||
   vmlinux  +-+
   module1.ko   | BPF program |
   module2.ko   +-+
 ...

  This is because:

  a)  Unlike GCC, LLVM will only generate BTF for BPF programs.

  b)  GCC can generate BTF for whatever target with -gbtf, but there is no
  support for linking/deduplicating BTF in the linker.

  In the scenario above, the verifier needs access to the pointer tags of
  both the kernel types/declarations (conveyed in the DWARF and translated
  to BTF by pahole) and those of the BPF program (available directly in 
BTF).

  Another motivation for having the tag information in DWARF, unrelated to
  BPF and BTF, is that the drgn project (another DWARF consumer) also wants
  to benefit from these tags in order to differentiate between different
  kinds of pointers in the kernel.

3)  Conveying the tags in the generated BTF debug info.

  This is easy: the main purpose of having this info in BTF is for the
  compiled eBPF programs. The kernel verifier can then access the tags
  of pointers used by the eBPF programs.


For more information about these tags and the motivation behind them, please
refer to the following linux kernel discussions:

https://lore.kernel.org/bpf/20210914223004.244411-1-...@fb.com/
https://lore.kernel.org/bpf/20211012164838.3345699-1-...@fb.com/
https://lore.kernel.org/bpf/2022012604.1504583-1-...@fb.com/


What is in this patch series


This patch series adds support for these annotations in GCC. The implementation
is largely complete. However, in some cases the produced debug info (both DWARF
and BTF) differs significantly from that produced by LLVM. This issue is
discussed in detail below, along with a few specific questions for both GCC and
LLVM. Any input would be much appreciated.


Hi, David, Thanks for the RFC implementation! I will answer your
questions related to llvm and kernel.



Hi Yonghong, thanks for the answers!




Implementation Overview
===

To enable these annotations, two new C language attributes are added:
__attribute__((btf_decl_tag("foo")) and __attribute__((btf_type_tag("bar"))).
Both attributes accept a single arbitrary string constant argument, which will
be recorded in the generated DWARF and/or BTF debu

[PATCH 7/8] Output BTF DECL_TAG and TYPE_TAG types

2022-04-01 Thread David Faust via Gcc-patches
This patch updates btfout.cc to be aware of the DECL_TAG and TYPE_TAG
kinds and output them appropriately.

gcc/

* btfout.cc (get_btf_kind): Handle TYPE_TAG and DECL_TAG kinds.
(btf_calc_num_vbytes): Likewise.
(btf_asm_type): Likewise.
(output_asm_btf_vlen_bytes): Likewise.
---
 gcc/btfout.cc | 28 
 1 file changed, 28 insertions(+)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 31af50521da..f291cd925be 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -136,6 +136,8 @@ get_btf_kind (uint32_t ctf_kind)
 case CTF_K_VOLATILE: return BTF_KIND_VOLATILE;
 case CTF_K_CONST:return BTF_KIND_CONST;
 case CTF_K_RESTRICT: return BTF_KIND_RESTRICT;
+case CTF_K_TYPE_TAG: return BTF_KIND_TYPE_TAG;
+case CTF_K_DECL_TAG: return BTF_KIND_DECL_TAG;
 default:;
 }
   return BTF_KIND_UNKN;
@@ -201,6 +203,7 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
 case BTF_KIND_CONST:
 case BTF_KIND_RESTRICT:
 case BTF_KIND_FUNC:
+case BTF_KIND_TYPE_TAG:
 /* These kinds have no vlen data.  */
   break;
 
@@ -238,6 +241,10 @@ btf_calc_num_vbytes (ctf_dtdef_ref dtd)
   vlen_bytes += vlen * sizeof (struct btf_var_secinfo);
   break;
 
+case BTF_KIND_DECL_TAG:
+  vlen_bytes += sizeof (struct btf_decl_tag);
+  break;
+
 default:
   break;
 }
@@ -636,6 +643,22 @@ btf_asm_type (ctf_container_ref ctfc, ctf_dtdef_ref dtd)
   dw2_asm_output_data (4, dtd->dtd_data.ctti_size, "btt_size: %uB",
   dtd->dtd_data.ctti_size);
   return;
+case BTF_KIND_DECL_TAG:
+  {
+   /* A decl tag might refer to (be the child DIE of) a variable. Try to
+  lookup the parent DIE's CTF variable, and if it exists point to the
+  corresponding BTF variable. This is an odd construction - we have a
+  'type' which refers to a variable, rather than the reverse.  */
+   dw_die_ref parent = dw_get_die_parent (dtd->dtd_key);
+   ctf_dvdef_ref dvd = ctf_dvd_lookup (ctfc, parent);
+   if (dvd)
+ {
+   unsigned int var_id =
+ *(btf_var_ids->get (dvd)) + num_types_added + 1;
+   dw2_asm_output_data (4, var_id, "btt_type");
+   return;
+ }
+  }
 default:
   break;
 }
@@ -949,6 +972,11 @@ output_asm_btf_vlen_bytes (ctf_container_ref ctfc, 
ctf_dtdef_ref dtd)
 at this point.  */
   gcc_unreachable ();
 
+case BTF_KIND_DECL_TAG:
+  dw2_asm_output_data (4, dtd->dtd_u.dtu_btfnote.component_idx,
+  "decltag_compidx");
+  break;
+
 default:
   /* All other BTF type kinds have no variable length data.  */
   break;
-- 
2.35.1



[PATCH 8/8] testsuite: Add tests for BTF tags

2022-04-01 Thread David Faust via Gcc-patches
This commit adds tests for the tags, in BTF and in DWARF.

gcc/teststuite/

* gcc.dg/debug/btf/btf-decltag-func.c: New test.
* gcc.dg/debug/btf/btf-decltag-sou.c: Likewise.
* gcc.dg/debug/btf/btf-decltag-typedef.c: Likewise.
* gcc.dg/debug/btf/btf-typetag-1.c: Likewise.
* gcc.dg/debug/dwarf2/annotation-1.c: Likewise.
---
 .../gcc.dg/debug/btf/btf-decltag-func.c   | 18 ++
 .../gcc.dg/debug/btf/btf-decltag-sou.c| 34 +++
 .../gcc.dg/debug/btf/btf-decltag-typedef.c| 15 
 .../gcc.dg/debug/btf/btf-typetag-1.c  | 20 +++
 .../gcc.dg/debug/dwarf2/annotation-1.c| 29 
 5 files changed, 116 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-typetag-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/dwarf2/annotation-1.c

diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
new file mode 100644
index 000..aa2c31aaa32
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-func.c
@@ -0,0 +1,18 @@
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 4 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+
+#define __tag1 __attribute__((btf_decl_tag("decl-tag-1")))
+#define __tag2 __attribute__((btf_decl_tag("decl-tag-2")))
+#define __tag3 __attribute__((btf_decl_tag("decl-tag-3")))
+
+extern int bar (int __tag1, int __tag2) __tag3;
+
+int __tag1 __tag2 foo (int arg1, int *arg2 __tag2)
+  {
+return bar (arg1 + 1, *arg2 + 2);
+  }
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
new file mode 100644
index 000..be89d0d32de
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-sou.c
@@ -0,0 +1,34 @@
+
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 16 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0\[\t \]+\[^\n\]*decltag_compidx" 
2 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x1\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x2\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x3\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x4\[\t 
\]+\[^\n\]*decltag_compidx" 1 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 6 } } */
+
+#define __tag1 __attribute__((btf_decl_tag("decl-tag-1")))
+#define __tag2 __attribute__((btf_decl_tag("decl-tag-2")))
+#define __tag3 __attribute__((btf_decl_tag("decl-tag-3")))
+
+struct t {
+  int a;
+  long b __tag3;
+  char c __tag2 __tag3;
+} __tag1 __tag2;
+
+struct t my_t __tag1 __tag3;
+
+
+union u {
+  char one __tag1 __tag2;
+  short two;
+  int three __tag1;
+  long four __tag1 __tag2 __tag3;
+  long long five __tag2;
+} __tag3;
+
+union u my_u __tag2;
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c
new file mode 100644
index 000..75be876f949
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-decltag-typedef.c
@@ -0,0 +1,15 @@
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1100\[\t 
\]+\[^\n\]*btt_info" 3 } } */
+/* { dg-final { scan-assembler-times "\[\t \]0x\[\t 
\]+\[^\n\]*decltag_compidx" 3 } } */
+
+#define __tag1 __attribute__((btf_decl_tag("decl-tag-1")))
+#define __tag2 __attribute__((btf_decl_tag("decl-tag-2")))
+#define __tag3 __attribute__((btf_decl_tag("decl-tag-3")))
+
+struct s { int a; } __tag1;
+
+typedef struct s * sptr __tag2;
+
+sptr my_sptr __tag3;
diff --git a/gcc/testsuite/gcc.dg/debug/btf/btf-typetag-1.c 
b/gcc/testsuite/gcc.dg/debug/btf/btf-typetag-1.c
new file mode 100644
index 000..4b05663385f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/debug/btf/btf-typetag-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile )  */
+/* { dg-options "-O0 -gbtf -dA" } */
+
+/* { dg-final { scan-assembler-times "\[\t \]0x1200\[\t 
\]+\[^\n\]*btt_info" 4 } } */
+
+#define __tag1 __attribute__((btf_type_tag("tag1")))
+#define __tag2 __attribute__((btf_type_tag("tag2")))
+#define __tag3 __attribute__((btf_type_tag("tag3")))
+
+int __tag1 * x;
+const int __tag2 * y;
+
+struct a;
+
+struct b
+{
+  struct a __tag2 __tag3 * inner_a;
+};
+
+struct b my_b;
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/a

[PATCH 6/8] dwarf2ctf: convert tag DIEs to CTF types

2022-04-01 Thread David Faust via Gcc-patches
This patch makes the DWARF-to-CTF conversion process aware of the new
DW_TAG_GNU_annotation DIEs. The DIEs are converted to CTF_K_DECL_TAG or
CTF_K_TYPE_TAG types as approprate and added to the compilation unit CTF
container.

gcc/

* dwarf2ctf.cc (handle_btf_tags): New function.
(gen_ctf_sou_type): Call it here, if appropriate. Don't try to
create member types for children that are not DW_TAG_member.
(gen_ctf_function_type): Call handle_btf_tags if appropriate.
(gen_ctf_variable): Likewise.
(gen_ctf_function): Likewise.
(gen_ctf_type): Likewise.
---
 gcc/dwarf2ctf.cc | 113 ++-
 1 file changed, 112 insertions(+), 1 deletion(-)

diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
index 32495cf4307..8811ec3e878 100644
--- a/gcc/dwarf2ctf.cc
+++ b/gcc/dwarf2ctf.cc
@@ -32,6 +32,12 @@ along with GCC; see the file COPYING3.  If not see
 static ctf_id_t
 gen_ctf_type (ctf_container_ref, dw_die_ref);
 
+static void
+gen_ctf_variable (ctf_container_ref, dw_die_ref);
+
+static void
+handle_btf_tags (ctf_container_ref, dw_die_ref, ctf_id_t, int);
+
 /* All the DIE structures we handle come from the DWARF information
generated by GCC.  However, there are three situations where we need
to create our own created DIE structures because GCC doesn't
@@ -547,6 +553,7 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
   /* Now process the struct members.  */
   {
 dw_die_ref c;
+int idx = 0;
 
 c = dw_get_die_child (sou);
 if (c)
@@ -559,6 +566,12 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
 
  c = dw_get_die_sib (c);
 
+ if (dw_get_die_tag (c) != DW_TAG_member)
+   continue;
+
+ if (c == dw_get_die_child (sou))
+   idx = 0;
+
  field_name = get_AT_string (c, DW_AT_name);
  field_type = ctf_get_AT_type (c);
  field_location = ctf_get_AT_data_member_location (c);
@@ -626,6 +639,12 @@ gen_ctf_sou_type (ctf_container_ref ctfc, dw_die_ref sou, 
uint32_t kind)
 field_name,
 field_type_id,
 field_location);
+
+ /* Handle BTF tags on the member.  */
+ if (btf_debuginfo_p ())
+   handle_btf_tags (ctfc, c, sou_type_id, idx);
+
+ idx++;
}
   while (c != dw_get_die_child (sou));
   }
@@ -716,6 +735,9 @@ gen_ctf_function_type (ctf_container_ref ctfc, dw_die_ref 
function,
  arg_type = gen_ctf_type (ctfc, ctf_get_AT_type (c));
  /* Add the argument to the existing CTF function type.  */
  ctf_add_function_arg (ctfc, function, arg_name, arg_type);
+
+ if (btf_debuginfo_p ())
+   handle_btf_tags (ctfc, c, function_type_id, i - 1);
}
  else
/* This is a local variable.  Ignore.  */
@@ -814,6 +836,11 @@ gen_ctf_variable (ctf_container_ref ctfc, dw_die_ref die)
   /* Generate the new CTF variable and update global counter.  */
   (void) ctf_add_variable (ctfc, var_name, var_type_id, die, external_vis);
   ctfc->ctfc_num_global_objts += 1;
+
+  /* Handle any BTF tags on the variable.  */
+  if (btf_debuginfo_p ())
+handle_btf_tags (ctfc, die, CTF_NULL_TYPEID, -1);
+
 }
 
 /* Add a CTF function record for the given input DWARF DIE.  */
@@ -831,8 +858,12 @@ gen_ctf_function (ctf_container_ref ctfc, dw_die_ref die)
  counter.  Note that DWARF encodes function types in both
  DW_TAG_subroutine_type and DW_TAG_subprogram in exactly the same
  way.  */
-  (void) gen_ctf_function_type (ctfc, die, true /* from_global_func */);
+  function_type_id = gen_ctf_function_type (ctfc, die, true /* 
from_global_func */);
   ctfc->ctfc_num_global_funcs += 1;
+
+  /* Handle any BTF tags on the function itself.  */
+  if (btf_debuginfo_p ())
+handle_btf_tags (ctfc, die, function_type_id, -1);
 }
 
 /* Add CTF type record(s) for the given input DWARF DIE and return its type id.
@@ -909,6 +940,10 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
   break;
 }
 
+  /* Handle any BTF tags on the type.  */
+  if (btf_debuginfo_p () && !unrecog_die)
+handle_btf_tags (ctfc, die, type_id, -1);
+
   /* For all types unrepresented in CTF, use an explicit CTF type of kind
  CTF_K_UNKNOWN.  */
   if ((type_id == CTF_NULL_TYPEID) && (!unrecog_die))
@@ -917,6 +952,82 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
   return type_id;
 }
 
+/* BTF support. Handle any BTF tags attached to a given DIE, and generate
+   intermediate CTF types for them. Type tags are inserted into the type chain
+   at this point. The return value is the CTF type ID of the last type tag
+   created (for type chaining), or the same as the argument TYPE_ID if there 
are
+   no type tags.
+   Note that despite the name, the BTF spec seems to allow decl tags on types
+   as well as dec

[PATCH 5/8] ctfc: Add support to pass through BTF annotations

2022-04-01 Thread David Faust via Gcc-patches
BTF generation currently relies on the internal CTF representation to
convert debug info from DWARF dies. This patch adds a new internal
header, "ctf-int.h", which defines CTF kinds to be used internally to
represent BTF tags which must pass through the CTF container. It also
adds a new type for representing information specific to those tags, and
a member for that type in ctf_dtdef.

This patch also updates ctf_add_reftype to accept a const char * name,
and add it for the newly added type.

gcc/

* ctf-int.h: New file.
* ctfc.cc (ctf_add_reftype): Add NAME parameter. Pass it to
ctf_add_generic call.
(ctf_add_pointer): Update ctf_add_reftype call accordingly.
* ctfc.h (ctf_add_reftype): Analogous change.
(ctf_btf_annotation): New.
(ctf_dtdef): Add member for it.
(enum ctf_dtu_d_union_enum): Likewise.
* dwarf2ctf.cc (gen_ctf_modifier_type): Update call to
ctf_add_reftype accordingly.
---
 gcc/ctf-int.h| 29 +
 gcc/ctfc.cc  | 11 +++
 gcc/ctfc.h   | 17 ++---
 gcc/dwarf2ctf.cc |  2 +-
 4 files changed, 51 insertions(+), 8 deletions(-)
 create mode 100644 gcc/ctf-int.h

diff --git a/gcc/ctf-int.h b/gcc/ctf-int.h
new file mode 100644
index 000..fb5f4aacad6
--- /dev/null
+++ b/gcc/ctf-int.h
@@ -0,0 +1,29 @@
+/* ctf-int.h - GCC internal definitions used for CTF debug info.
+   Copyright (C) 2022 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+.  */
+
+#ifndef GCC_CTF_INT_H
+#define GCC_CTF_INT_H 1
+
+/* These CTF kinds only exist as a bridge to generating BTF types for
+   BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG. They do not correspond to any
+   representable type kind in CTF.  */
+#define CTF_K_DECL_TAG  62
+#define CTF_K_TYPE_TAG  63
+
+#endif /* GCC_CTF_INT_H */
diff --git a/gcc/ctfc.cc b/gcc/ctfc.cc
index 6fe44d2e8d4..031a6fff65d 100644
--- a/gcc/ctfc.cc
+++ b/gcc/ctfc.cc
@@ -107,6 +107,9 @@ ctf_dtu_d_union_selector (ctf_dtdef_ref ctftype)
   return CTF_DTU_D_ARGUMENTS;
 case CTF_K_SLICE:
   return CTF_DTU_D_SLICE;
+case CTF_K_DECL_TAG:
+case CTF_K_TYPE_TAG:
+  return CTF_DTU_D_BTFNOTE;
 default:
   /* The largest member as default.  */
   return CTF_DTU_D_ARRAY;
@@ -394,15 +397,15 @@ ctf_add_encoded (ctf_container_ref ctfc, uint32_t flag, 
const char * name,
 }
 
 ctf_id_t
-ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
-uint32_t kind, dw_die_ref die)
+ctf_add_reftype (ctf_container_ref ctfc, uint32_t flag, const char * name,
+ctf_id_t ref, uint32_t kind, dw_die_ref die)
 {
   ctf_dtdef_ref dtd;
   ctf_id_t type;
 
   gcc_assert (ref <= CTF_MAX_TYPE);
 
-  type = ctf_add_generic (ctfc, flag, NULL, &dtd, die);
+  type = ctf_add_generic (ctfc, flag, name, &dtd, die);
   dtd->dtd_data.ctti_info = CTF_TYPE_INFO (kind, flag, 0);
   /* Caller of this API must guarantee that a CTF type with id = ref already
  exists.  This will also be validated for us at link-time.  */
@@ -514,7 +517,7 @@ ctf_id_t
 ctf_add_pointer (ctf_container_ref ctfc, uint32_t flag, ctf_id_t ref,
 dw_die_ref die)
 {
-  return (ctf_add_reftype (ctfc, flag, ref, CTF_K_POINTER, die));
+  return (ctf_add_reftype (ctfc, flag, NULL, ref, CTF_K_POINTER, die));
 }
 
 ctf_id_t
diff --git a/gcc/ctfc.h b/gcc/ctfc.h
index 18c93c802a0..51f43cd01cb 100644
--- a/gcc/ctfc.h
+++ b/gcc/ctfc.h
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dwarf2ctf.h"
 #include "ctf.h"
 #include "btf.h"
+#include "ctf-int.h"
 
 /* Invalid CTF type ID definition.  */
 
@@ -151,6 +152,13 @@ typedef struct GTY (()) ctf_func_arg
 
 #define ctf_farg_list_next(elem) ((ctf_func_arg_t *)((elem)->farg_next))
 
+/* BTF support: a BTF type tag or decl tag.  */
+
+typedef struct GTY (()) ctf_btf_annotation
+{
+  uint32_t component_idx;
+} ctf_btf_annotation_t;
+
 /* Type definition for CTF generation.  */
 
 struct GTY ((for_user)) ctf_dtdef
@@ -173,6 +181,8 @@ struct GTY ((for_user)) ctf_dtdef
 ctf_func_arg_t * GTY ((tag ("CTF_DTU_D_ARGUMENTS"))) dtu_argv;
 /* slice.  */
 ctf_sliceinfo_t GTY ((tag ("CTF_DTU_D_SLICE"))) dtu_slice;
+/* btf annotation.  */
+ctf_btf_annotation_t GTY ((tag ("CTF_DTU_D_BTFNOTE"))) dtu_btfnote;
   } dtd_u;
 };
 
@@ -212,7 +222,8 @@ enum ctf_dtu_d_union

[PATCH 4/8] dwarf: create BTF decl and type tag DIEs

2022-04-01 Thread David Faust via Gcc-patches
The "btf_decl_tag" and "btf_type_tag" attributes are handled by
constructing DW_TAG_LLVM_annotation DIEs. The DIEs are children of the
declarations or types which they annotate, and convey the annotation via
a string constant.

Currently, all generation of these DIEs is gated behind
btf_debuginfo_p (). That is, they will not be generated nor output
unless BTF debug information is generated. The DIEs will be output in
DWARF if both -gbtf and -gdwarf are supplied by the user.

gcc/

* dwarf2out.cc (gen_btf_decl_tag_dies): New function.
(gen_btf_type_tag_dies): Likewise.
(modified_type_die): Call them here, if appropriate.
(gen_formal_parameter_die): Likewise.
(gen_typedef_die): Likewise.
(gen_type_die): Likewise.
(gen_decl_die): Likewise.
---
 gcc/dwarf2out.cc | 102 +++
 1 file changed, 102 insertions(+)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 35322fb5f6e..8f59213f96e 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -13612,6 +13612,78 @@ long_double_as_float128 (tree type)
   return NULL_TREE;
 }
 
+/* BTF support. Given a tree T, which may be a decl or a type, process any
+   "btf_decl_tag" attributes on T, provided in ATTR. Construct
+   DW_TAG_GNU_annotation DIEs appropriately as children of TARGET, usually
+   the DIE for T.  */
+
+static void
+gen_btf_decl_tag_dies (tree t, dw_die_ref target)
+{
+  dw_die_ref die;
+  tree attr;
+
+  if (t == NULL_TREE || !target)
+return;
+
+  if (TYPE_P (t))
+attr = lookup_attribute ("btf_decl_tag", TYPE_ATTRIBUTES (t));
+  else if (DECL_P (t))
+attr = lookup_attribute ("btf_decl_tag", DECL_ATTRIBUTES (t));
+  else
+/* This is an error.  */
+gcc_unreachable ();
+
+  while (attr != NULL_TREE)
+{
+  die = new_die (DW_TAG_GNU_annotation, target, t);
+  add_name_attribute (die, IDENTIFIER_POINTER (get_attribute_name (attr)));
+  add_AT_string (die, DW_AT_const_value,
+TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr;
+  attr = TREE_CHAIN (attr);
+}
+
+  /* Strip the decl tag attribute to avoid creating multiple copies if we hit
+ this tree node again in some recursive call.  */
+  if (TYPE_P (t))
+TYPE_ATTRIBUTES (t) =
+  remove_attribute ("btf_decl_tag", TYPE_ATTRIBUTES (t));
+  else if (DECL_P (t))
+DECL_ATTRIBUTES (t) =
+  remove_attribute ("btf_decl_tag", DECL_ATTRIBUTES (t));
+}
+
+/* BTF support. Given a tree TYPE, process any "btf_type_tag" attributes on
+   TYPE. Construct DW_TAG_GNU_annotation DIEs appropriately as children of
+   TARGET, usually the DIE for TYPE.  */
+
+static void
+gen_btf_type_tag_dies (tree type, dw_die_ref target)
+{
+  dw_die_ref die;
+  tree attr;
+
+  if (type == NULL_TREE || !target)
+return;
+
+  gcc_assert (TYPE_P (type));
+
+  attr = lookup_attribute ("btf_type_tag", TYPE_ATTRIBUTES (type));
+  while (attr != NULL_TREE)
+{
+  die = new_die (DW_TAG_GNU_annotation, target, type);
+  add_name_attribute (die, IDENTIFIER_POINTER (get_attribute_name (attr)));
+  add_AT_string (die, DW_AT_const_value,
+TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr;
+  attr = TREE_CHAIN (attr);
+}
+
+  /* Strip the type tag attribute to avoid creating multiple copies if we hit
+ this type again in some recursive call.  */
+  TYPE_ATTRIBUTES (type) =
+remove_attribute ("btf_type_tag", TYPE_ATTRIBUTES (type));
+}
+
 /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging
entry that chains the modifiers specified by CV_QUALS in front of the
given type.  REVERSE is true if the type is to be interpreted in the
@@ -14010,6 +14082,10 @@ modified_type_die (tree type, int cv_quals, bool 
reverse,
   if (TYPE_ARTIFICIAL (type))
 add_AT_flag (mod_type_die, DW_AT_artificial, 1);
 
+  /* BTF support. Handle any "btf_type_tag" attributes on the type.  */
+  if (btf_debuginfo_p ())
+gen_btf_type_tag_dies (type, mod_type_die);
+
   return mod_type_die;
 }
 
@@ -22986,6 +23062,10 @@ gen_formal_parameter_die (tree node, tree origin, bool 
emit_name_p,
   gcc_unreachable ();
 }
 
+  /* BTF Support */
+  if (btf_debuginfo_p ())
+gen_btf_decl_tag_dies (node, parm_die);
+
   return parm_die;
 }
 
@@ -26060,6 +26140,10 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
 
   if (get_AT (type_die, DW_AT_name))
 add_pubtype (decl, type_die);
+
+  /* BTF: handle attribute btf_decl_tag which may appear on the typedef.  */
+  if (btf_debuginfo_p ())
+gen_btf_decl_tag_dies (decl, type_die);
 }
 
 /* Generate a DIE for a struct, class, enum or union type.  */
@@ -26373,6 +26457,20 @@ gen_type_die (tree type, dw_die_ref context_die)
  if (die)
check_die (die);
}
+
+  /* BTF support. Handle any "btf_type_tag" or "btf_decl_tag" attributes
+on the type, constructing annotation DIEs as appropriate.  */
+  if (btf_debuginfo_p

[PATCH 3/8] c-family: Add BTF tag attribute handlers

2022-04-01 Thread David Faust via Gcc-patches
This patch adds attribute handlers in GCC for two attributes already
supported in LLVM: "btf_decl_tag" and "btf_type_tag". Both attributes
accept a single string constant argument, and are used to add arbitrary
annotations to debug information generated for the types/decls to which
they apply.

gcc/c-family/

* c-attribs.cc (c_common_attribute_table): Add new attributes
btf_decl_tag and btf_type_tag.
(handle_btf_decl_tag_attribute): New.
(handle_btf_type_tag_attribute): Likewise.
---
 gcc/c-family/c-attribs.cc | 45 +++
 1 file changed, 45 insertions(+)

diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index 111a33f405a..ec52f6defb4 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -174,6 +174,9 @@ static tree handle_signed_bool_precision_attribute (tree *, 
tree, tree, int,
bool *);
 static tree handle_retain_attribute (tree *, tree, tree, int, bool *);
 
+static tree handle_btf_decl_tag_attribute (tree *, tree, tree, int, bool *);
+static tree handle_btf_type_tag_attribute (tree *, tree, tree, int, bool *);
+
 /* Helper to define attribute exclusions.  */
 #define ATTR_EXCL(name, function, type, variable)  \
   { name, function, type, variable }
@@ -555,6 +558,12 @@ const struct attribute_spec c_common_attribute_table[] =
  handle_dealloc_attribute, NULL },
   { "tainted_args",  0, 0, true,  false, false, false,
  handle_tainted_args_attribute, NULL },
+
+  { "btf_type_tag",   1, 1, false, true, false, false,
+ handle_btf_type_tag_attribute, NULL },
+  { "btf_decl_tag",   1, 1, false, false, false, false,
+ handle_btf_decl_tag_attribute, NULL },
+
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
 };
 
@@ -5854,6 +5863,42 @@ handle_tainted_args_attribute (tree *node, tree name, 
tree, int,
   return NULL_TREE;
 }
 
+/* Handle a "btf_decl_tag" attribute; arguments as in
+   struct attribute_spec.handler.   */
+
+static tree
+handle_btf_decl_tag_attribute (tree *, tree name, tree args, int,
+  bool *no_add_attrs)
+{
+  if (!args)
+*no_add_attrs = true;
+  else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+{
+  error ("%qE attribute requires a string", name);
+  *no_add_attrs = true;
+}
+
+  return NULL_TREE;
+}
+
+/* Handle a "btf_type_tag" attribute; arguments as in
+   struct attribute_spec.handler.   */
+
+static tree
+handle_btf_type_tag_attribute (tree *, tree name, tree args, int,
+  bool *no_add_attrs)
+{
+  if (!args)
+*no_add_attrs = true;
+  else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
+{
+  error ("%qE attribute requires a string", name);
+  *no_add_attrs = true;
+}
+
+  return NULL_TREE;
+}
+
 /* Attempt to partially validate a single attribute ATTR as if
it were to be applied to an entity OPER.  */
 
-- 
2.35.1



[PATCH 2/8] include: Add BTF tag defines to dwarf2 and btf

2022-04-01 Thread David Faust via Gcc-patches
include/

* btf.h: Add BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG defines. Update
comments.
(struct btf_decl_tag): New.
* dwarf2.def: Add new DWARF extension DW_TAG_GNU_annotation.
---
 include/btf.h  | 17 +++--
 include/dwarf2.def |  4 
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/include/btf.h b/include/btf.h
index 78b551ced23..37deaef8b48 100644
--- a/include/btf.h
+++ b/include/btf.h
@@ -69,7 +69,7 @@ struct btf_type
 
   /* SIZE is used by INT, ENUM, STRUCT, UNION, DATASEC kinds.
  TYPE is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, FUNC,
- FUNC_PROTO and VAR kinds.  */
+ FUNC_PROTO, VAR and DECL_TAG kinds.  */
   union
   {
 uint32_t size; /* Size of the entire type, in bytes.  */
@@ -109,7 +109,9 @@ struct btf_type
 #define BTF_KIND_VAR   14  /* Variable.  */
 #define BTF_KIND_DATASEC   15  /* Section such as .bss or .data.  */
 #define BTF_KIND_FLOAT 16  /* Floating point.  */
-#define BTF_KIND_MAX   BTF_KIND_FLOAT
+#define BTF_KIND_DECL_TAG  17  /* Decl Tag.  */
+#define BTF_KIND_TYPE_TAG  18  /* Type Tag.  */
+#define BTF_KIND_MAX   BTF_KIND_TYPE_TAG
 #define NR_BTF_KINDS   (BTF_KIND_MAX + 1)
 
 /* For some BTF_KINDs, struct btf_type is immediately followed by
@@ -190,6 +192,17 @@ struct btf_var_secinfo
   uint32_t size;   /* Size (in bytes) of variable.  */
 };
 
+/* BTF_KIND_DECL_TAG is followed by a single struct btf_decl_tag, which
+   describes the tag location:
+   - If component_idx == -1, then the tag is applied to a struct, union,
+ variable or function.
+   - Otherwise it is applied to a struct/union member or function argument
+ with the given given index numbered 0..vlen-1.  */
+struct btf_decl_tag
+{
+  int32_t component_idx;
+};
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/dwarf2.def b/include/dwarf2.def
index 4214c80907a..e054890130a 100644
--- a/include/dwarf2.def
+++ b/include/dwarf2.def
@@ -174,6 +174,10 @@ DW_TAG (DW_TAG_GNU_formal_parameter_pack, 0x4108)
are properly part of DWARF 5.  */
 DW_TAG (DW_TAG_GNU_call_site, 0x4109)
 DW_TAG (DW_TAG_GNU_call_site_parameter, 0x410a)
+
+/* Extension for BTF annotations.  */
+DW_TAG (DW_TAG_GNU_annotation, 0x6000)
+
 /* Extensions for UPC.  See: http://dwarfstd.org/doc/DWARF4.pdf.  */
 DW_TAG (DW_TAG_upc_shared_type, 0x8765)
 DW_TAG (DW_TAG_upc_strict_type, 0x8766)
-- 
2.35.1



[PATCH 1/8] dwarf: Add dw_get_die_parent function

2022-04-01 Thread David Faust via Gcc-patches
gcc/

* dwarf2out.cc (dw_get_die_parent): New function.
* dwarf2out.h (dw_get_die_parent): Declare it here.
---
 gcc/dwarf2out.cc | 8 
 gcc/dwarf2out.h  | 1 +
 2 files changed, 9 insertions(+)

diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 5681b01749a..35322fb5f6e 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -5235,6 +5235,14 @@ dw_get_die_sib (dw_die_ref die)
   return die->die_sib;
 }
 
+/* Return a reference to the parent of a given DIE.  */
+
+dw_die_ref
+dw_get_die_parent (dw_die_ref die)
+{
+  return die->die_parent;
+}
+
 /* Add an address constant attribute value to a DIE.  When using
dwarf_split_debug_info, address attributes in dies destined for the
final executable should be direct references--setting the parameter
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 656ef94afde..e6962fb4848 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -455,6 +455,7 @@ extern dw_die_ref lookup_type_die (tree);
 
 extern dw_die_ref dw_get_die_child (dw_die_ref);
 extern dw_die_ref dw_get_die_sib (dw_die_ref);
+extern dw_die_ref dw_get_die_parent (dw_die_ref);
 extern enum dwarf_tag dw_get_die_tag (dw_die_ref);
 
 /* Data about a single source file.  */
-- 
2.35.1



[PATCH 0/8][RFC] Support BTF decl_tag and type_tag annotations

2022-04-01 Thread David Faust via Gcc-patches
Hello,

This patch series is a first attempt at adding support for:

- Two new C-language-level attributes that allow to associate (to "tag")
  particular declarations and types with arbitrary strings. As explained below,
  this is intended to be used to, for example, characterize certain pointer
  types.

- The conveyance of that information in the DWARF output in the form of a new
  DIE: DW_TAG_GNU_annotation.

- The conveyance of that information in the BTF output in the form of two new
  kinds of BTF objects: BTF_KIND_DECL_TAG and BTF_KIND_TYPE_TAG.

All of these facilities are being added to the eBPF ecosystem, and support for
them exists in some form in LLVM. However, as we shall see, we have found some
problems implementing them so some discussion is in order.

Purpose
===

1)  Addition of C-family language constructs (attributes) to specify free-text
tags on certain language elements, such as struct fields.

The purpose of these annotations is to provide additional information about
types, variables, and function paratemeters of interest to the kernel. A
driving use case is to tag pointer types within the linux kernel and eBPF
programs with additional semantic information, such as '__user' or '__rcu'.

For example, consider the linux kernel function do_execve with the
following declaration:

  static int do_execve(struct filename *filename,
 const char __user *const __user *__argv,
 const char __user *const __user *__envp);

Here, __user could be defined with these annotations to record semantic
information about the pointer parameters (e.g., they are user-provided) in
DWARF and BTF information. Other kernel facilites such as the eBPF verifier
can read the tags and make use of the information.

2)  Conveying the tags in the generated DWARF debug info.

The main motivation for emitting the tags in DWARF is that the Linux kernel
generates its BTF information via pahole, using DWARF as a source:

++  BTF  BTF   +--+
| pahole |---> vmlinux.btf --->| verifier |
++ +--+
^^
||
  DWARF |BTF |
||
 vmlinux  +-+
 module1.ko   | BPF program |
 module2.ko   +-+
   ...

This is because:

a)  Unlike GCC, LLVM will only generate BTF for BPF programs.

b)  GCC can generate BTF for whatever target with -gbtf, but there is no
support for linking/deduplicating BTF in the linker.

In the scenario above, the verifier needs access to the pointer tags of
both the kernel types/declarations (conveyed in the DWARF and translated
to BTF by pahole) and those of the BPF program (available directly in BTF).

Another motivation for having the tag information in DWARF, unrelated to
BPF and BTF, is that the drgn project (another DWARF consumer) also wants
to benefit from these tags in order to differentiate between different
kinds of pointers in the kernel.

3)  Conveying the tags in the generated BTF debug info.

This is easy: the main purpose of having this info in BTF is for the
compiled eBPF programs. The kernel verifier can then access the tags
of pointers used by the eBPF programs.


For more information about these tags and the motivation behind them, please
refer to the following linux kernel discussions:

  https://lore.kernel.org/bpf/20210914223004.244411-1-...@fb.com/
  https://lore.kernel.org/bpf/20211012164838.3345699-1-...@fb.com/
  https://lore.kernel.org/bpf/2022012604.1504583-1-...@fb.com/


What is in this patch series


This patch series adds support for these annotations in GCC. The implementation
is largely complete. However, in some cases the produced debug info (both DWARF
and BTF) differs significantly from that produced by LLVM. This issue is
discussed in detail below, along with a few specific questions for both GCC and
LLVM. Any input would be much appreciated.


Implementation Overview
===

To enable these annotations, two new C language attributes are added:
__attribute__((btf_decl_tag("foo")) and __attribute__((btf_type_tag("bar"))).
Both attributes accept a single arbitrary string constant argument, which will
be recorded in the generated DWARF and/or BTF debugging information. They have
no effect on code generation.

Note that we are using the same attribute names as LLVM, which include "btf"
in the name. This may be controversial, as these tags are not really
BTF-specific. A different name may be more appropriate. There was much
discussion about naming in the proposal for the functionali

Re: [PATCH v2] bpf: ensure correct string offsets in BTF.ext

2022-01-18 Thread David Faust via Gcc-patches




On 1/18/22 13:18, Jose E. Marchesi wrote:


Hi David.


[Changed from v1: Adjust to account for file renaming so patch applies.]

BPF CO-RE relocations contain offsets to strings buffered in the BTF
string table. These BTF-specific strings are stored in memory in the
CTF auxilliary strtab, which at output time is concatenated onto the end
of the standard strtab.

Previously, these string offsets were computed at the time the
relocations were created. But strings could be added to the standard
strtab after this point, causing the offsets to no longer be correct.

Compute the offsets just before output instead, when they are sure to no
longer change.

Tested for bpf-unknown-none. OK to install?
Thanks.


OK.
Thanks.


Pushed, thanks





gcc/ChangeLog:

* config/bpf/coreout.cc (bpf_core_reloc_add): Do not account
for base strtab offset yet as it may change.
(output_asm_btfext_core_reloc): Do so here instead.
(output_btfext_core_sections): Likewise.
---
  gcc/config/bpf/coreout.cc | 14 +-
  1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
index 4ec12ecd305..cceaaa969cc 100644
--- a/gcc/config/bpf/coreout.cc
+++ b/gcc/config/bpf/coreout.cc
@@ -168,11 +168,8 @@ bpf_core_reloc_add (const tree type, const char * 
section_name,
bpf_core_reloc_ref bpfcr = ggc_cleared_alloc ();
ctf_container_ref ctfc = ctf_get_tu_ctfc ();
  
-  /* Buffer the access string in the auxiliary strtab. Since the two string

- tables are concatenated, add the length of the first to the offset.  */
-  size_t strtab_len = ctfc_get_strtab_len (ctfc, CTF_STRTAB);
+  /* Buffer the access string in the auxiliary strtab.  */
ctf_add_string (ctfc, buf, &(bpfcr->bpfcr_astr_off), CTF_AUX_STRTAB);
-  bpfcr->bpfcr_astr_off += strtab_len;
  
bpfcr->bpfcr_type = get_btf_id (ctf_lookup_tree_type (ctfc, type));

bpfcr->bpfcr_insn_label = label;
@@ -191,7 +188,6 @@ bpf_core_reloc_add (const tree type, const char * 
section_name,
sec = ggc_cleared_alloc ();
  
ctf_add_string (ctfc, section_name, &sec->name_offset, CTF_AUX_STRTAB);

-  sec->name_offset += strtab_len;
if (strcmp (section_name, ""))
  ctfc->ctfc_aux_strlen += strlen (section_name) + 1;
  
@@ -287,6 +283,9 @@ output_btfext_header (void)

  static void
  output_asm_btfext_core_reloc (bpf_core_reloc_ref bpfcr)
  {
+  bpfcr->bpfcr_astr_off += ctfc_get_strtab_len (ctf_get_tu_ctfc (),
+   CTF_STRTAB);
+
dw2_assemble_integer (4, gen_rtx_LABEL_REF (Pmode, 
bpfcr->bpfcr_insn_label));
fprintf (asm_out_file, "\t%s bpfcr_insn\n", ASM_COMMENT_START);
  
@@ -323,6 +322,11 @@ output_btfext_core_sections (void)

/* Section name offset, refers to the offset of a string with the name 
of
 the section to which these CORE relocations refer, e.g. '.text'.
 The string is buffered in the BTF strings table.  */
+
+  /* BTF specific strings are in CTF_AUX_STRTAB, which is concatenated
+after CTF_STRTAB. Add the length of STRTAB to the final offset.  */
+  sec->name_offset += ctfc_get_strtab_len (ctf_get_tu_ctfc (), CTF_STRTAB);
+
dw2_asm_output_data (4, sec->name_offset,  
"btfext_secinfo_sec_name_off");
dw2_asm_output_data (4, vec_safe_length (sec->relocs),
   "btfext_secinfo_num_recs");


Re: [PATCH v2] bpf: write CO-RE relocation record size only once

2022-01-18 Thread David Faust via Gcc-patches




On 1/18/22 13:17, Jose E. Marchesi wrote:


Hi David.


[Changed from v1: Adjust to account for file renaming so patch applies.]

The CO-RE relocation record size should be written only once in the
.BTF.ext section, not once for each section with relocations.

Tested for bpf-unknown-none. OK to install?


This is OK.
Thanks for the patch.


Pushed, thanks




Thanks.

gcc/ChangeLog:

* config/bpf/coreout.cc (output_btfext_header): Account for
4-byte record size in core_relo_len.
(output_btfext_core_sections): Only write record size once.
* config/bpf/coreout.h (btf_ext_section_header): Delete unused
member.

gcc/testsuite/ChangeLog:

* gcc.target/bpf/core-section-1.c: Adjust expected record size
occurrences.
---
  gcc/config/bpf/coreout.cc | 14 +-
  gcc/config/bpf/coreout.h  |  1 -
  gcc/testsuite/gcc.target/bpf/core-section-1.c |  2 +-
  3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
index f8ca2804207..4ec12ecd305 100644
--- a/gcc/config/bpf/coreout.cc
+++ b/gcc/config/bpf/coreout.cc
@@ -259,7 +259,7 @@ output_btfext_header (void)
uint32_t core_relo_off = 0, core_relo_len = 0;
  
/* Header core_relo_len is the sum total length in bytes of all CO-RE

- relocation sections.  */
+ relocation sections, plus the 4 byte record size.  */
size_t i;
bpf_core_section_ref sec;
core_relo_len += vec_safe_length (bpf_core_sections)
@@ -269,6 +269,9 @@ output_btfext_header (void)
  core_relo_len +=
vec_safe_length (sec->relocs) * sizeof (struct btf_ext_reloc);
  
+  if (core_relo_len)

+core_relo_len += sizeof (uint32_t);
+
dw2_asm_output_data (4, func_info_off, "func_info_offset");
dw2_asm_output_data (4, func_info_len, "func_info_len");
  
@@ -310,12 +313,13 @@ output_btfext_core_sections (void)

  {
size_t i;
bpf_core_section_ref sec;
+
+  /* BTF Ext section info. */
+  dw2_asm_output_data (4, sizeof (struct btf_ext_reloc),
+  "btfext_core_info_rec_size");
+
FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec)
  {
-  /* BTF Ext section info. */
-  dw2_asm_output_data (4, sizeof (struct btf_ext_reloc),
-  "btfext_secinfo_rec_size");
-
/* Section name offset, refers to the offset of a string with the name 
of
 the section to which these CORE relocations refer, e.g. '.text'.
 The string is buffered in the BTF strings table.  */
diff --git a/gcc/config/bpf/coreout.h b/gcc/config/bpf/coreout.h
index a9d7e364ba3..3c7bdfd8c2f 100644
--- a/gcc/config/bpf/coreout.h
+++ b/gcc/config/bpf/coreout.h
@@ -33,7 +33,6 @@ extern "C"
  
  struct btf_ext_section_header

  {
-  uint32_t kind;
uint32_t sec_name_off;
uint32_t num_records;
  };
diff --git a/gcc/testsuite/gcc.target/bpf/core-section-1.c 
b/gcc/testsuite/gcc.target/bpf/core-section-1.c
index 031acd5292e..4f16b087c1a 100644
--- a/gcc/testsuite/gcc.target/bpf/core-section-1.c
+++ b/gcc/testsuite/gcc.target/bpf/core-section-1.c
@@ -35,4 +35,4 @@ int bar_func (struct T *t)
  /* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
  /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
  /* { dg-final { scan-assembler-times "bpfcr_type" 2 } } */
-/* { dg-final { scan-assembler-times "btfext_secinfo_rec_size" 2 } } */
+/* { dg-final { scan-assembler-times "btfext_core_info_rec_size" 1 } } */


[PATCH v2] bpf: ensure correct string offsets in BTF.ext

2022-01-18 Thread David Faust via Gcc-patches
[Changed from v1: Adjust to account for file renaming so patch applies.]

BPF CO-RE relocations contain offsets to strings buffered in the BTF
string table. These BTF-specific strings are stored in memory in the
CTF auxilliary strtab, which at output time is concatenated onto the end
of the standard strtab.

Previously, these string offsets were computed at the time the
relocations were created. But strings could be added to the standard
strtab after this point, causing the offsets to no longer be correct.

Compute the offsets just before output instead, when they are sure to no
longer change.

Tested for bpf-unknown-none. OK to install?
Thanks.

gcc/ChangeLog:

* config/bpf/coreout.cc (bpf_core_reloc_add): Do not account
for base strtab offset yet as it may change.
(output_asm_btfext_core_reloc): Do so here instead.
(output_btfext_core_sections): Likewise.
---
 gcc/config/bpf/coreout.cc | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
index 4ec12ecd305..cceaaa969cc 100644
--- a/gcc/config/bpf/coreout.cc
+++ b/gcc/config/bpf/coreout.cc
@@ -168,11 +168,8 @@ bpf_core_reloc_add (const tree type, const char * 
section_name,
   bpf_core_reloc_ref bpfcr = ggc_cleared_alloc ();
   ctf_container_ref ctfc = ctf_get_tu_ctfc ();
 
-  /* Buffer the access string in the auxiliary strtab. Since the two string
- tables are concatenated, add the length of the first to the offset.  */
-  size_t strtab_len = ctfc_get_strtab_len (ctfc, CTF_STRTAB);
+  /* Buffer the access string in the auxiliary strtab.  */
   ctf_add_string (ctfc, buf, &(bpfcr->bpfcr_astr_off), CTF_AUX_STRTAB);
-  bpfcr->bpfcr_astr_off += strtab_len;
 
   bpfcr->bpfcr_type = get_btf_id (ctf_lookup_tree_type (ctfc, type));
   bpfcr->bpfcr_insn_label = label;
@@ -191,7 +188,6 @@ bpf_core_reloc_add (const tree type, const char * 
section_name,
   sec = ggc_cleared_alloc ();
 
   ctf_add_string (ctfc, section_name, &sec->name_offset, CTF_AUX_STRTAB);
-  sec->name_offset += strtab_len;
   if (strcmp (section_name, ""))
 ctfc->ctfc_aux_strlen += strlen (section_name) + 1;
 
@@ -287,6 +283,9 @@ output_btfext_header (void)
 static void
 output_asm_btfext_core_reloc (bpf_core_reloc_ref bpfcr)
 {
+  bpfcr->bpfcr_astr_off += ctfc_get_strtab_len (ctf_get_tu_ctfc (),
+   CTF_STRTAB);
+
   dw2_assemble_integer (4, gen_rtx_LABEL_REF (Pmode, bpfcr->bpfcr_insn_label));
   fprintf (asm_out_file, "\t%s bpfcr_insn\n", ASM_COMMENT_START);
 
@@ -323,6 +322,11 @@ output_btfext_core_sections (void)
   /* Section name offset, refers to the offset of a string with the name of
 the section to which these CORE relocations refer, e.g. '.text'.
 The string is buffered in the BTF strings table.  */
+
+  /* BTF specific strings are in CTF_AUX_STRTAB, which is concatenated
+after CTF_STRTAB. Add the length of STRTAB to the final offset.  */
+  sec->name_offset += ctfc_get_strtab_len (ctf_get_tu_ctfc (), CTF_STRTAB);
+
   dw2_asm_output_data (4, sec->name_offset,  
"btfext_secinfo_sec_name_off");
   dw2_asm_output_data (4, vec_safe_length (sec->relocs),
   "btfext_secinfo_num_recs");
-- 
2.34.1



[PATCH v2] bpf: write CO-RE relocation record size only once

2022-01-18 Thread David Faust via Gcc-patches
[Changed from v1: Adjust to account for file renaming so patch applies.]

The CO-RE relocation record size should be written only once in the
.BTF.ext section, not once for each section with relocations.

Tested for bpf-unknown-none. OK to install?
Thanks.

gcc/ChangeLog:

* config/bpf/coreout.cc (output_btfext_header): Account for
4-byte record size in core_relo_len.
(output_btfext_core_sections): Only write record size once.
* config/bpf/coreout.h (btf_ext_section_header): Delete unused
member.

gcc/testsuite/ChangeLog:

* gcc.target/bpf/core-section-1.c: Adjust expected record size
occurrences.
---
 gcc/config/bpf/coreout.cc | 14 +-
 gcc/config/bpf/coreout.h  |  1 -
 gcc/testsuite/gcc.target/bpf/core-section-1.c |  2 +-
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/gcc/config/bpf/coreout.cc b/gcc/config/bpf/coreout.cc
index f8ca2804207..4ec12ecd305 100644
--- a/gcc/config/bpf/coreout.cc
+++ b/gcc/config/bpf/coreout.cc
@@ -259,7 +259,7 @@ output_btfext_header (void)
   uint32_t core_relo_off = 0, core_relo_len = 0;
 
   /* Header core_relo_len is the sum total length in bytes of all CO-RE
- relocation sections.  */
+ relocation sections, plus the 4 byte record size.  */
   size_t i;
   bpf_core_section_ref sec;
   core_relo_len += vec_safe_length (bpf_core_sections)
@@ -269,6 +269,9 @@ output_btfext_header (void)
 core_relo_len +=
   vec_safe_length (sec->relocs) * sizeof (struct btf_ext_reloc);
 
+  if (core_relo_len)
+core_relo_len += sizeof (uint32_t);
+
   dw2_asm_output_data (4, func_info_off, "func_info_offset");
   dw2_asm_output_data (4, func_info_len, "func_info_len");
 
@@ -310,12 +313,13 @@ output_btfext_core_sections (void)
 {
   size_t i;
   bpf_core_section_ref sec;
+
+  /* BTF Ext section info. */
+  dw2_asm_output_data (4, sizeof (struct btf_ext_reloc),
+  "btfext_core_info_rec_size");
+
   FOR_EACH_VEC_ELT (*bpf_core_sections, i, sec)
 {
-  /* BTF Ext section info. */
-  dw2_asm_output_data (4, sizeof (struct btf_ext_reloc),
-  "btfext_secinfo_rec_size");
-
   /* Section name offset, refers to the offset of a string with the name of
 the section to which these CORE relocations refer, e.g. '.text'.
 The string is buffered in the BTF strings table.  */
diff --git a/gcc/config/bpf/coreout.h b/gcc/config/bpf/coreout.h
index a9d7e364ba3..3c7bdfd8c2f 100644
--- a/gcc/config/bpf/coreout.h
+++ b/gcc/config/bpf/coreout.h
@@ -33,7 +33,6 @@ extern "C"
 
 struct btf_ext_section_header
 {
-  uint32_t kind;
   uint32_t sec_name_off;
   uint32_t num_records;
 };
diff --git a/gcc/testsuite/gcc.target/bpf/core-section-1.c 
b/gcc/testsuite/gcc.target/bpf/core-section-1.c
index 031acd5292e..4f16b087c1a 100644
--- a/gcc/testsuite/gcc.target/bpf/core-section-1.c
+++ b/gcc/testsuite/gcc.target/bpf/core-section-1.c
@@ -35,4 +35,4 @@ int bar_func (struct T *t)
 /* { dg-final { scan-assembler-times "ascii \"foo_sec.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "ascii \"bar_sec.0\"\[\t 
\]+\[^\n\]*btf_aux_string" 1 } } */
 /* { dg-final { scan-assembler-times "bpfcr_type" 2 } } */
-/* { dg-final { scan-assembler-times "btfext_secinfo_rec_size" 2 } } */
+/* { dg-final { scan-assembler-times "btfext_core_info_rec_size" 1 } } */
-- 
2.34.1



  1   2   >