[Bug target/107479] New: bpf: add __builtin_btf_type_id
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107479 Bug ID: 107479 Summary: bpf: add __builtin_btf_type_id Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com Target Milestone: --- LLVM supports a BPF builtin: __builtin_btf_type_id (param, flag) which returns the BTF type id of 'param' to the program, and records a BPF CO-RE relocation according to 'flag'. We should support the same functionality in GCC. These are the relevant changes in LLVM and clang: https://reviews.llvm.org/D74572 https://reviews.llvm.org/D74668
[Bug target/107480] New: bpf: add __builtin_preserve_type_info
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107480 Bug ID: 107480 Summary: bpf: add __builtin_preserve_type_info Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com Target Milestone: --- LLVM supports a BPF builtin: __builtin_preserve_type_info (param, flag) which is used to generate additional relocations for the Compile Once - Run Everywhere (CO-RE) mechanism. This builtin produces a relocation recording the information about the type of 'param', such as it's size or whether or not it exists on the host kernel, according to 'flag'. This information is returned to the program and patched by the eBPF loader during loading. We should support this functionality in GCC. These are the relevant changes in LLVM: https://reviews.llvm.org/D83878 https://reviews.llvm.org/D83242
[Bug target/107481] New: bpf: add __builtin_preserve_enum_value
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107481 Bug ID: 107481 Summary: bpf: add __builtin_preserve_enum_value Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com Target Milestone: --- LLVM supports a builtin: __builtin_preserve_enum_value (param, flag) which is used to generate additional relocations for the Compile Once - Run Everywhere (CO-RE) mechanism. This builtin produces a CO-RE relocation recording information about the enumerator value in 'param' according to 'flag', and returns that information to the program. For example, the integer value of the enumerator, or a boolean value representing whether or not that enumerator exists on the host kernel. These values are patched by the eBPF loader according to the CO-RE relocation. We should support the same functionality in GCC. These are the relevant changes in LLVM: https://reviews.llvm.org/D83878 https://reviews.llvm.org/D83242
[Bug target/107846] error: result of '8000 << 8' requires 22 bits to represent, but 'short int' only has 16 bits
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107846 --- Comment #1 from David Faust --- I think this is a bug in the test itself (or with these macros from libbpf). libbpf/src/bpf_endian.h #define ___bpf_mvb(x, b, n, m) ((__u##b)(x) << (b-(n+1)*8) >> (b-8) << (m*8)) #define ___bpf_swab16(x) ((__u16)( \ ___bpf_mvb(x, 16, 0, 1) | \ ___bpf_mvb(x, 16, 1, 0))) # define __bpf_constant_htons(x)___bpf_swab16(x) In tools/testing/selftests/bpf/progs/test_tc_tunnel.c: static const int cfg_port = 8000; static const int cfg_udp_src = 2; ... then at e.g. line 276 if (tcph.dest != __bpf_constant_htons(cfg_port)) return TC_ACT_OK; Expanding this __bpf_constant_htons macro: __bpf_constant_htons (cfg_port) __bpf_constant_htons (8000) ((__u16)(8000) << (16-(0+1)*8) >> (16-8) << (1*8) ((__u16)(8000) << (16-(1)*8) >> (8) << 8) ((__u16)(8000) << (8) >> 8 << 8 ((__u16)(8000) << 8) ...which raises the shift-overflow warning.
[Bug target/106773] libbpf: failed to find BTF info for global/extern symbol 'bpf_link_fops'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106773 --- Comment #3 from David Faust --- There are two remaining issues: 1. We are missing support for 'linkage=extern' encoding for variables, so 'bpf_link_fops' and others are incorrectly marked with 'linkage=global' instead. 2. 'bpf_link_fops' variable is encoded as 'void' type not 'const void'. This is a result of the BTF being generated from internal DWARF representation. The distinction seems to be intentionally removed in dwarf2out.cc:add_type_attribute(), with the later side-effect that looking up the type DIE for the variable when generating BTF actually fails and falls back to the default 'void'. I have an implementation for (1) in progress. For (2) I need to understand why the 'void'/'const void' distinction is removed in DWARF and how to work around it.
[Bug target/106773] libbpf: failed to find BTF info for global/extern symbol 'bpf_link_fops'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106773 --- Comment #4 from David Faust --- Created attachment 53993 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53993&action=edit proposed patch Should fix the remaining issues with 'extern' linkage and the missing 'const' modifier (and includes the earlier partial fixes in this bug)
[Bug target/106773] libbpf: failed to find BTF info for global/extern symbol 'bpf_link_fops'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106773 --- Comment #8 from David Faust --- (In reply to James Hilliard from comment #5) > (In reply to David Faust from comment #4) > > Created attachment 53993 [details] > > proposed patch > > > > Should fix the remaining issues with 'extern' linkage and the missing > > 'const' modifier (and includes the earlier partial fixes in this bug) > > Fixes the reported test failure but some others(unclear if related to this > bug) are still failing such as tailcall_bpf2bpf3.c: Thanks for testing and confirming. > $ /home/buildroot/bpf-next/tools/testing/selftests/bpf/tools/sbin/bpftool > --debug gen object > /home/buildroot/bpf-next/tools/testing/selftests/bpf/bpf_gcc/ > tailcall_bpf2bpf3.bpf.linked1.o > /home/buildroot/bpf-next/tools/testing/selftests/bpf/bpf_gcc/ > tailcall_bpf2bpf3.bpf.o > libbpf: linker: adding object file > '/home/buildroot/bpf-next/tools/testing/selftests/bpf/bpf_gcc/ > tailcall_bpf2bpf3.bpf.o'... > libbpf: failed to find BTF info for global/extern symbol 'llvm.bpf.load.word' > Error: failed to link > https://github.com/torvalds/linux/blob/v6.1-rc7/tools/testing/selftests/bpf/bpf_legacy.h unsigned long long load_word(void *skb, unsigned long long off) asm("llvm.bpf.load.word"); Looks like LLVM-specific inline asm to use their llvm.bpf.load.word intrinsic. GCC has equivalent __builtin_load_{byte,half,word} target builtins. > There's also this error during skeleton generation for kfunc_call_test.c: > ... > libbpf: failed to find BTF for extern 'bpf_kfunc_call_test2': -22 Hm, looks like we are OK for extern variables but are mis-generating something (or missing something) for extern funcs still. Will look into this.
[Bug target/106773] libbpf: failed to find BTF info for global/extern symbol 'bpf_link_fops'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106773 David Faust changed: What|Removed |Added Attachment #53993|0 |1 is obsolete|| --- Comment #9 from David Faust --- Created attachment 54002 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54002&action=edit updated patch Update the 'extern' variable marking, and also mark 'extern' funcs.
[Bug target/106773] libbpf: failed to find BTF info for global/extern symbol 'bpf_link_fops'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106773 --- Comment #13 from David Faust --- Created attachment 54017 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54017&action=edit DATASEC entries for extern funcs Applies on top of 54002: updated patch Adds emission of DATASEC entries for extern funcs. Rough, needs cleanup.
[Bug target/106773] libbpf: failed to find BTF info for global/extern symbol 'bpf_link_fops'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106773 David Faust changed: What|Removed |Added Attachment #54017|0 |1 is obsolete|| --- Comment #15 from David Faust --- Created attachment 54021 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54021&action=edit [v2] DATASEC entries for extern funcs v2 fixes an off-by-one bug introduced in the patch which was causing libbpf: Invalid BTF total size
[Bug target/107843] error: incompatible type for argument in ___bpf_ctx_cast2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107843 --- Comment #1 from David Faust --- Looks like this is an issue with passing void* where an enum type is expected in a function call. This is not specific to the BPF backend. Not entirely clear to me whether this is expected or a bug, but it does differ from llvm behavior. Reproducer below, tried with a few gccs, same behavior: today (6 Dec 2022)'s master 81476bc4f4a20bcf3af7ac2548c2322d48499402 gcc-12 (Debian 12.2.0-9) 12.2.0 gcc-10 (Debian 10.4.0-5) 10.4.0 gcc-8 (Debian 8.4.0-7) 8.4.0 $ cat enumcast.c enum E { E_FOO = 0, E_BAR = 1, }; int foo_enum (enum E e); int bar_enum (enum E e) { return foo_enum ((void *) e); } int foo_int (int x); int bar_int (int x) { return foo_int ((void *) x); } $ gcc -c enumcast.c -o enumcast.o enumcast.c: In function ‘bar_enum’: enumcast.c:10:20: error: incompatible type for argument 1 of ‘foo_enum’ 10 | return foo_enum ((void *) e); |^~ || |void * enumcast.c:7:22: note: expected ‘enum E’ but argument is of type ‘void *’ 7 | int foo_enum (enum E e); | ~~~^ enumcast.c: In function ‘bar_int’: enumcast.c:16:19: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 16 | return foo_int ((void *) x); | ^ enumcast.c:16:19: warning: passing argument 1 of ‘foo_int’ makes integer from pointer without a cast [-Wint-conversion] 16 | return foo_int ((void *) x); | ^~ | | | void * enumcast.c:13:18: note: expected ‘int’ but argument is of type ‘void *’ 13 | int foo_int (int x); | ^ $ clang -c enumcast.c -o enumcast.o enumcast.c:10:20: warning: incompatible pointer to integer conversion passing 'void *' to parameter of type 'enum E' [-Wint-conversion] return foo_enum ((void *) e); ^~ enumcast.c:7:22: note: passing argument to parameter 'e' here int foo_enum (enum E e); ^ enumcast.c:16:19: warning: cast to 'void *' from smaller integer type 'int' [-Wint-to-void-pointer-cast] return foo_int ((void *) x); ^~ enumcast.c:16:19: warning: incompatible pointer to integer conversion passing 'void *' to parameter of type 'int' [-Wint-conversion] return foo_int ((void *) x); ^~ enumcast.c:13:18: note: passing argument to parameter 'x' here int foo_int (int x); ^ 3 warnings generated.
[Bug target/106745] segfault in bpf_core_get_sou_member_index
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106745 David Faust changed: What|Removed |Added CC||david.faust at oracle dot com --- Comment #1 from David Faust --- Thanks, I've reproduced the failure and found the issue. The code which generates the CO-RE relocations isn't correctly handling anonymous inner struct/union decls. So for example: struct core_reloc_flavors___weird { struct { int b; }; union { int a; int c; }; }; Asking to generate a CO-RE relo for access to a, b or c here will trigger the SEGV. Working on a fix.
[Bug target/109253] libbpf: failed to find BTF info for global/extern symbol '__divdi3'
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109253 --- Comment #1 from David Faust --- See: https://gcc.gnu.org/pipermail/gcc-patches/2022-December/608152.html Also related as Andrew pointed out in the above thread: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=48783
[Bug debug/110073] [14 regression] btfout.cc format errors break bootstrap
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110073 --- Comment #1 from David Faust --- Created attachment 55234 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55234&action=edit alternate proposed patch Thank you for catching this, and for the fix! With the proposed patch on linux x86_64 I see the following: ../../../gcc/gcc/btfout.cc: In function ‘void btf_asm_func_type(ctf_container_ref, ctf_dtdef_ref, size_t)’: ../../../gcc/gcc/btfout.cc:952:31: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 4 has type ‘size_t’ {aka ‘long unsigned int’} [-Wformat=] 952 |"TYPE %u BTF_KIND_FUNC '%s'", | ~^ | | | unsigned int | %lu 953 |num_types_added + num_vars_added + 1 + i, | | | | size_t {aka long unsigned int} I believe %zu instead of %u should work. Alternatively, a small refactor to the offending code makes it behave in line with the other functions (to properly use a ctf_id_t, and then PRIu64 as in your patch). But I haven't verified this on solaris/x86 yet.
[Bug debug/110073] [14 regression] btfout.cc format errors break bootstrap
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110073 --- Comment #4 from David Faust --- (In reply to Iain Sandoe from comment #3) > (In reply to Iain Sandoe from comment #2) > > there seems to be a second fail on x86_64 darwin on line 970. > > I tried the alternate patch on a number of x86_64, i686 and power Darwin > systems and bootstrap is restored. Thanks for confirming. I'll go ahead and send it to the list.
[Bug debug/110073] [14 regression] btfout.cc format errors break bootstrap
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110073 --- Comment #6 from David Faust --- (In reply to Iain Sandoe from comment #5) > (In reply to David Faust from comment #4) > > (In reply to Iain Sandoe from comment #3) > > > (In reply to Iain Sandoe from comment #2) > > > > there seems to be a second fail on x86_64 darwin on line 970. > > > > > > I tried the alternate patch on a number of x86_64, i686 and power Darwin > > > systems and bootstrap is restored. > > > > Thanks for confirming. I'll go ahead and send it to the list. > > I think with bootstrap fixes, you are allowed a bit more independence - i.e. > can go ahead and apply - but now needs resolution with Alex's patch, OK, thanks. And yes I just ran into the conflict. Rebasing now.
[Bug debug/110073] [14 regression] btfout.cc format errors break bootstrap
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110073 --- Comment #9 from David Faust --- (In reply to Alex Coplan from comment #8) > Thanks for the follow-up fix and apologies for the mid-air collision, I > didn't see the %zu problem on the target I was testing. No problem, thanks for the fixes :) I'm slow on the patch formatting etc. Hopefully these are all taken care of now between the two patches.
[Bug target/114431] bpf: GCC generates unverifiable code for systemd restrict_fs_bpf
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114431 David Faust changed: What|Removed |Added CC||david.faust at oracle dot com --- Comment #7 from David Faust --- Patch above had some fallout for non-BPF targets. I pushed the below to fix that. The behavior for BPF is unchanged. https://gcc.gnu.org/g:8075477f81ae8d0abf64b80dfbd179151f91b417 commit r14-9876-g8075477f81ae8d0abf64b80dfbd179151f91b417 Author: David Faust Date: Mon Apr 8 11:10:41 2024 -0700 btf: emit symbol refs in DATASEC entries only for BPF [PR114608]
[Bug target/107844] error: argument is not a field access for __builtin_preserve_field_info
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107844 --- Comment #1 from David Faust --- Looks like this is a result of the combination of how the bpf_core_field_exists macro is defined and some sort of optimization(?) happening in the C frontend. Consider: struct S { unsigned short x; char c[12]; }; int foo () { int has_c = bpf_core_field_exists (struct S, c); return has_c; } The bpf_core_field_exists macro expands to: int has_c = __builtin_preserve_field_infotypeof(struct S) *)0)->c), BPF_RELO_FIELD_EXISTS); For some reason, for array members specifically, this construction results in the tree for the parameter when resolving the builtin being simply: (gdb) pt param constant 2> i.e. a pointer to 0x2, the offset of 'c' in a 'struct S' mapped at 0x0. For non-array members, 'param' is some kind of as I'd expect. This gives us two problems: a) We cannot distinguish an array member from a non-member constant-value pointer. b) We cannot correctly compute information for the CO-RE relocation. For example, in this case BPF_RELO_FIELD_BYTE_SIZE will be calculated as 8 (size of pointer), not 12 (size of the array). I'm not sure how to resolve this and support the existing helper macros in the kernel/libbpf. Might need some change in the C frontend, or to somehow pass more information to the target_resolve_overloaded_builtin hook...
[Bug target/107844] error: argument is not a field access for __builtin_preserve_field_info
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107844 --- Comment #3 from David Faust --- Thanks for the info Andrew. I'll look at __builtin_offsetof. As for the implementation in clang, I can point to some bits relevant to the builtin itself: llvm-project/clang/lib/CodeGen/CGBuiltin.cpp CodeGenFunction::EmitBPFBuiltinExpr () llvm-project/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp BPFAbstractMemberAccess::GetFieldInfo () But I am less familiar with the surrounding machinery such as their parsing and type systems..
[Bug target/107844] error: argument is not a field access for __builtin_preserve_field_info
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107844 --- Comment #5 from David Faust --- (In reply to Andrew Pinski from comment #4) > (In reply to David Faust from comment #3) > > Thanks for the info Andrew. I'll look at __builtin_offsetof. > > > > As for the implementation in clang, I can point to some bits relevant to > > the builtin itself: > > llvm-project/clang/lib/CodeGen/CGBuiltin.cpp > > CodeGenFunction::EmitBPFBuiltinExpr () > > > > llvm-project/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp > > BPFAbstractMemberAccess::GetFieldInfo () > > > > But I am less familiar with the surrounding machinery such as their > > parsing and type systems.. > > So I looked (First off I am shocked they don't have target functions to > handle the builtins and every target builtin is handled in that file seems > wrong), and you are handed the AST before folding. This is different from > GCC where it is you are handed it after folding. Aha! I had never realized this difference until now. Thanks for pointing that out! > > So I think we need some special handling in the c (and C++) parser to handle > this. I suspect we want to do the full handling of the builtin > (bpf_core_field_exists) in the parser rather than the macro expanded view of > it too. Similar to how offsetof is handled ... > Of course this will need some modifications to the bpf headers too. And that > solves some other issues too. Yes, I see. I'll have to study the parser a little since I have not touched it before, but the approach makes sense. I wonder if it would be feasible and/or worthwhile to add some sort of TARGET_PARSE_BUILTIN hook to enable this sort of handling for any other targets which may want it..? Maybe that can wait. In any case, thank you very much for the suggestions.
[Bug target/108790] New: bpf: gcc emits malformed ldxdw instruction at -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108790 Bug ID: 108790 Summary: bpf: gcc emits malformed ldxdw instruction at -O2 Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com CC: cupertino.miranda at oracle dot com Target Milestone: --- Target: bpf With -O2 GCC emits a malformed ldxdw instruction in some cases: $ cat ldxdw.c unsigned long long test () { return *((unsigned long long *) 0x4000); } $ bpf-unknown-none-gcc -c -O2 ldxdw.c -o ldxdw.o /tmp/ccsuVj7l.s: Assembler messages: /tmp/ccsuVj7l.s:7: Error: unrecognized form of instruction `ldxdw %r0,16384' ldxdw (and all other {ldx,stx}{b,h,w,dw} insns should have a form like ldxdw %rX, [%rY + OFFSET] Looks like we need a better constraint on the memory operand in *mov. Testing a patch for this now.
[Bug target/109068] New: bpf: "error: too many function arguments for eBPF" for always_inline function
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109068 Bug ID: 109068 Summary: bpf: "error: too many function arguments for eBPF" for always_inline function Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com CC: cupertino.miranda at oracle dot com, jemarch at gcc dot gnu.org Target Milestone: --- Target: bpf BPF calling convention does not support function calls with more than 5 arguments. But if the function is inlined this restriction should be relaxed. Many convenience macros for BPF in the kernel make use of always_inline functions, and the expansion of the macro uses can result in an always_inline function with >5 args. There are several examples of this in the BPF selftests, so GCC fails to compile those tests. e.g. on bpf-next: linux/tools/testing/selftests/bpf/progs/bpf_syscall_macro.c and corresponding BPF_KSYSCALL macro def in linux/tools/testing/selftests/bpf/tools/include/bpf/bpf_tracing.h duplicated from linux/tools/lib/bpf/bpf_tracing.h clang compiles these tests without issue. We should fix the BPF backend check for function arguments to allow calls to inline functions with >5 args. $ cat args.c inline __attribute__((always_inline)) int foo (int a, int b, int c, int d, int e, int f) { return a + b + c + d + e + f; } int bar (int x) { return foo (x, x*2, x*3, x*4, x*5, x*6); } $ bpf-unknown-none-gcc -c args.c -o args.o args.c: In function ‘foo’: args.c:2:5: error: too many function arguments for eBPF 2 | int foo (int a, int b, int c, int d, int e, int f) | ^~~
[Bug debug/110439] New: Missing DW_TAG_typedef for variable with attribute of typedef'd type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110439 Bug ID: 110439 Summary: Missing DW_TAG_typedef for variable with attribute of typedef'd type Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com Target Milestone: --- $ cat typedef-skip-1.c typedef int foo; foo __attribute__((may_alias)) attr_foo; foo plain_foo; DW_AT_type in the variable DIE for 'attr_foo' refers to the base int type, while for 'plain_foo' it refers to the typedef DIE I would expect: $ gcc -g -c typedef-skip-1.c $ readelf -wi typedef-skip-1.o <0>: Abbrev Number: 2 (DW_TAG_compile_unit) DW_AT_producer: (indirect string, offset: 0): GNU C17 12.2.0 -mtune=generic -march=x86-64 -g -fasynchronous-unwind-tables <11> DW_AT_language: 29 (C11) <12> DW_AT_name: (indirect line string, offset: 0): typedef-skip-1.c <16> DW_AT_comp_dir: (indirect line string, offset: 0x11): /home/dfaust/playpen <1a> DW_AT_stmt_list : 0 <1><1e>: Abbrev Number: 3 (DW_TAG_typedef) <1f> DW_AT_name: foo <23> DW_AT_decl_file : 1 <24> DW_AT_decl_line : 1 <25> DW_AT_decl_column : 13 <26> DW_AT_type: <0x2a> <1><2a>: Abbrev Number: 4 (DW_TAG_base_type) <2b> DW_AT_byte_size : 4 <2c> DW_AT_encoding: 5(signed) <2d> DW_AT_name: int <1><31>: Abbrev Number: 1 (DW_TAG_variable) <32> DW_AT_name: (indirect string, offset: 0x4c): attr_foo <36> DW_AT_decl_file : 1 <36> DW_AT_decl_line : 2 <37> DW_AT_decl_column : 32 <38> DW_AT_type: <0x2a> <3c> DW_AT_external: 1 <3c> DW_AT_location: 9 byte block: 3 0 0 0 0 0 0 0 0 (DW_OP_addr: 0) <1><46>: Abbrev Number: 1 (DW_TAG_variable) <47> DW_AT_name: (indirect string, offset: 0x55): plain_foo <4b> DW_AT_decl_file : 1 <4b> DW_AT_decl_line : 3 <4c> DW_AT_decl_column : 5 <4d> DW_AT_type: <0x1e> <51> DW_AT_external: 1 <51> DW_AT_location: 9 byte block: 3 4 0 0 0 0 0 0 0 (DW_OP_addr: 4) <1><5b>: Abbrev Number: 0 DWARF output by clang has the DW_TAG_typedef DIE in DW_AT_type for both variables: $ clang -c -g typedef-skip-1.c -o typedef-skip-1.o.clang $ readelf -wi typedef-skip-1.o.clang <1><1e>: Abbrev Number: 2 (DW_TAG_variable) <1f> DW_AT_name: (indexed string: 0x3): attr_foo <20> DW_AT_type: <0x29> <24> DW_AT_external: 1 <24> DW_AT_decl_file : 0 <25> DW_AT_decl_line : 2 <26> DW_AT_location: (DW_OP_addrx <0>) <1><29>: Abbrev Number: 3 (DW_TAG_typedef) <2a> DW_AT_type: <0x31> <2e> DW_AT_name: (indexed string: 0x5): foo <2f> DW_AT_decl_file : 0 <30> DW_AT_decl_line : 1 <1><31>: Abbrev Number: 4 (DW_TAG_base_type) <32> DW_AT_name: (indexed string: 0x4): int <33> DW_AT_encoding: 5(signed) <34> DW_AT_byte_size : 4 <1><35>: Abbrev Number: 2 (DW_TAG_variable) <36> DW_AT_name: (indexed string: 0x6): plain_foo <37> DW_AT_type: <0x29> <3b> DW_AT_external: 1 <3b> DW_AT_decl_file : 0 <3c> DW_AT_decl_line : 3 <3d> DW_AT_location: (DW_OP_addrx <0x1>) <1><40>: Abbrev Number: 0 Note this isn't strictly related to 'may_alias', I just found it to be a reliable reproducer. I tripped on this while working on a patch to support a BPF feature, the btf_type_tag attribute. I think this happens because this lookup in modified_type_die: /* If we do, then we can just use its DIE, if it exists. */ if (qualified_type) { mod_type_die = lookup_type_die (qualified_type); finds the typedef DIE for the un-__attribute__-ed use 'foo', but returns NULL for the __attribute__-ed use of 'foo': Breakpoint 6, modified_type_die (type=, cv_quals=0, reverse=false, context_die=) at ../../../gcc/gcc/dwarf2out.cc:13631 (gdb) pt type constant 32> unit-size constant 4> align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 0x776215e8 attributes > precision:32 min max > ... 13699 if (qualified_type) (gdb) 13701 mod_type_die = lookup_type_die (qualified_type); (gdb) 13706 if (mod_type_die (gdb) p mod_type_die $1 = Then recurses with return modified_type_die (DECL_ORIGINAL_TYPE (name), cv_quals, reverse, context_die); Where DECL_ORIGINAL_TYPE (name) is a plain integer type: constant 32> unit-size constant 4> align:32 warn_if_not_align:0 symtab:-142864960 alias-set -1 canonical-type 0x776215e8 precision:32 min max pointer_to_this > I am not 100% sure whether the GCC output is "strictly incorrect" DWA
[Bug debug/110439] Missing DW_TAG_typedef for variable with attribute of typedef'd type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110439 David Faust changed: What|Removed |Added CC||jemarch at gcc dot gnu.org --- Comment #2 from David Faust --- (In reply to Andrew Pinski from comment #1) > The may_alias does not apply directly to variables nor their types I use may_alias here as a placeholder, since it persists in the TREE representation through this point. I found this while implementing a new attribute (btf_type_tag, a BPF feature) which does apply directly to types with a similar representation in the TREE, which triggered the same behavior.
[Bug target/109558] bpf: support BTF and DWARF tag annotations for BPF
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109558 --- Comment #1 from David Faust --- v1 patch series for btf_decl_tag: https://gcc.gnu.org/pipermail/gcc-patches/2023-July/624156.html This also adds infrastructure which will be used for btf_type_tag.
[Bug target/109558] bpf: support BTF and DWARF tag annotations for BPF
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109558 --- Comment #2 from David Faust --- Patches for btf_type_tag WIP, but DWARF for type_tags in certain cases is incorrect seemingly due to PR debug/110439. I am still investigating. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110439
[Bug debug/112849] btf: wrong BTF_KIND_DATSEC entries for extern variables without known section
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112849 --- Comment #1 from David Faust --- Simple reproducer. Note how clang does not emit an entry in BTF_KIND_DATASEC for 'extern int a'. $ cat a.c extern int a; int b; int foo (void) { return a + b; } $ ~/toolchains/bpf/bin/bpf-unknown-none-gcc -gbtf -c a.c -o a.o $ /usr/sbin/bpftool btf dump file a.o [1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED [2] FUNC_PROTO '(anon)' ret_type_id=1 vlen=0 [3] VAR 'a' type_id=1, linkage=extern [4] VAR 'b' type_id=1, linkage=global [5] FUNC 'foo' type_id=2 linkage=global [6] DATASEC '.bss' size=0 vlen=2 type_id=3 offset=0 size=4 (VAR 'a') type_id=4 offset=0 size=4 (VAR 'b') $ ~/toolchains/llvm/bin/clang -target bpf -c -g a.c -o a.o $ /usr/sbin/bpftool btf dump file a.o [1] FUNC_PROTO '(anon)' ret_type_id=2 vlen=0 [2] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED [3] FUNC 'foo' type_id=1 linkage=global [4] VAR 'a' type_id=2, linkage=extern [5] VAR 'b' type_id=2, linkage=global [6] DATASEC '.bss' size=0 vlen=1 type_id=5 offset=0 size=4 (VAR 'b')
[Bug debug/112849] New: btf: wrong BTF_KIND_DATSEC entries for extern variables without known section
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112849 Bug ID: 112849 Summary: btf: wrong BTF_KIND_DATSEC entries for extern variables without known section Product: gcc Version: 14.0 Status: UNCONFIRMED Keywords: btf-debug, wrong-debug Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com CC: cupertino.miranda at oracle dot com, ibhagat at gcc dot gnu.org, jemarch at gcc dot gnu.org Target Milestone: --- When building bpf-next selftests with gcc trunk, we get the following error from libbpf: libbpf: linker: adding object file 'linked_vars1.bpf.o'... libbpf: linker: adding object file 'linked_vars2.bpf.o'... libbpf: global 'input_data1': section mismatch 4 vs 5 Error: failed to link 'linked_vars2.bpf.o': Invalid argument (22) Here libbpf is doing some form of linking of the two objects. 'input_data1' is declared and initialized in linked_vars1, and placed in .data. In linked_vars2 it is declared extern, however an entry for it is added in the .bss BTF_KIND_DATASEC record in linked_vars2.bpf.o. clang does not emit entries in BTF_KIND_DATASEC for extern variable decls without an explicit section e.g. via __attribute__((section(...))). gcc [7237] DATASEC '.bss' size=0 vlen=8 type_id=7059 offset=0 size=4 (VAR 'input_data1') <- type_id=7167 offset=0 size=4 (VAR 'input_bss1') <- type_id=7100 offset=0 size=4 (VAR 'output_sink2') type_id=7111 offset=0 size=4 (VAR 'output_rodata2') type_id=7065 offset=0 size=4 (VAR 'output_data2') type_id=7090 offset=0 size=4 (VAR 'output_bss2') type_id=7079 offset=0 size=4 (VAR 'input_bss_weak') type_id=7192 offset=0 size=4 (VAR 'input_bss2') clang [34] DATASEC '.bss' size=0 vlen=6 type_id=18 offset=0 size=4 (VAR 'input_bss2') type_id=19 offset=0 size=4 (VAR 'input_bss_weak') type_id=20 offset=0 size=4 (VAR 'output_bss2') type_id=21 offset=0 size=4 (VAR 'output_data2') type_id=22 offset=0 size=4 (VAR 'output_rodata2') type_id=23 offset=0 size=4 (VAR 'output_sink2') The problem is that when creating the BTF_KIND_DATASEC entires, gcc is incorrectly falling back to a default section name (like .bss) for variables, even if they are 'extern' decls. gcc should be changed to not emit entries in any BTF_KIND_DATASEC for extern variable decls without a known section.
[Bug debug/111735] incorrect BTF representation of forward-declared enums
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111735 David Faust changed: What|Removed |Added CC||david.faust at oracle dot com --- Comment #1 from David Faust --- Sorry for the delay, somehow I missed this until now. Confirmed... though this really ought to be further discussed and formalized with the kernel BPF folks. As of now, btf.rst does not specify any representation at all for forward-declared enums. And, it lists in 'encoding requirements' for BTF_KIND_ENUM that 'size' must be one of 1/2/4/8, so in a sense this de-facto representation is not really valid. IMO it would be better to adjust the BTF_KIND_FWD definition to support forward-declared enums. CTF for example encodes the kind of the forward in the 'type' field of its KIND_FWD, which in BTF is simply unused. Anyway, that can be raised for discussion on the bpf list. In the meanwhile, it should not be problematic to adapt GCC to follow clang and pahole in emitting KIND_ENUM with vlen=0.
[Bug debug/113566] New: btf: incorrect BTF_KIND_DATASEC entries for variables which are optimized out
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113566 Bug ID: 113566 Summary: btf: incorrect BTF_KIND_DATASEC entries for variables which are optimized out Product: gcc Version: 14.0 Status: UNCONFIRMED Keywords: btf-debug Severity: normal Priority: P3 Component: debug Assignee: unassigned at gcc dot gnu.org Reporter: david.faust at oracle dot com CC: david.faust at oracle dot com, jemarch at gcc dot gnu.org Target Milestone: --- Target: all Consider a simple program: $ cat static.c static int a = 5; int foo (int x) { return a + x; } When compiled with -O2, variable 'a' is optimized away, and its use is replaced with a literal 5 in the resulting object code. For all targets except BPF, BTF is emitted at early_finish always. For the BPF target, if -mco-re is in effect, then BTF is emitted at finish rather than early_finish. The combination of -O2 with emitting BTF at early_finish causes incorrect BTF_KIND_DATASEC entries to be emitted for all targets except BPF CO-RE: $ ~/toolchains/bpf/bin/bpf-unknown-none-gcc -c -gbtf -O2 -mco-re static.c -o static.o $ /usr/sbin/bpftool btf dump file static.o [1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED [2] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1 'x' type_id=1 [3] VAR 'a' type_id=1, linkage=static [4] FUNC 'foo' type_id=2 linkage=global $ ~/toolchains/bpf/bin/bpf-unknown-none-gcc -c -gbtf -O2 -mno-co-re static.c -o static.o $ /usr/sbin/bpftool btf dump file static.o [1] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED [2] FUNC_PROTO '(anon)' ret_type_id=1 vlen=1 'x' type_id=1 [3] VAR 'a' type_id=1, linkage=static [4] FUNC 'foo' type_id=2 linkage=global [5] DATASEC '.data' size=0 vlen=1 type_id=3 offset=0 size=4 (VAR 'a') (same for e.g. x86_64 with -gbtf) In either case, 'a' is optimized away, and is not allocated in .data: $ ~/toolchains/bpf/bin/bpf-unknown-none-objdump -dh static.o static.o: file format elf64-bpfle Sections: Idx Name Size VMA LMA File off Algn 0 .text 0018 0040 2**3 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .data 0058 2**0 CONTENTS, ALLOC, LOAD, DATA 2 .bss 0058 2**0 ALLOC ... So, the BTF_KIND_DATASEC entry claiming 'a' is allocated in .data is incorrect. Clang correctly does not generate such a DATASEC entry. The only case where the entry is correctly not generated by gcc is for the BPF target with -mco-re, since in that case the DATASEC entries will be generated at finish rather than early finish, by which time 'a' is known to be optimized away.