Re: Possible bugs in generated DATASEC BTF

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, 24 Sept 2022 at 01:49, Andrii Nakryiko
<andrii.nakryiko@xxxxxxxxx> wrote:
>
> On Fri, Sep 23, 2022 at 4:38 PM Kumar Kartikeya Dwivedi
> <memxor@xxxxxxxxx> wrote:
> >
> > On Sat, 24 Sept 2022 at 01:20, Andrii Nakryiko
> > <andrii.nakryiko@xxxxxxxxx> wrote:
> > >
> > > On Fri, Sep 23, 2022 at 3:32 PM Kumar Kartikeya Dwivedi
> > > <memxor@xxxxxxxxx> wrote:
> > > >
> > > > Hi,
> > > > For the following example:
> > > >
> > > > kkd@Legion ~/src/linux
> > > >  ; cat bpf.c
> > > > #define tag __attribute__((btf_decl_tag("tag")))
> > > >
> > > > int a tag;
> > > > int b tag;
> > > >
> > > > int main() {
> > > >         return a + b;
> > > > }
> > > >
> > > > --
> > > >
> > > > When I compile using:
> > > > clang -target bpf -O2 -g -c bpf.c
> > > >
> > > > For the BTF dump, I see:
> > > > [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 'main' type_id=1 linkage=global
> > > > [4] VAR 'a' type_id=2, linkage=global
> > > > [5] DECL_TAG 'tag' type_id=4 component_idx=-1
> > > > [6] VAR 'b' type_id=2, linkage=global
> > > > [7] DECL_TAG 'tag' type_id=6 component_idx=-1
> > > > [8] DATASEC '.bss' size=0 vlen=2
> > > >         type_id=4 offset=0 size=4 (VAR 'a')
> > > >         type_id=6 offset=0 size=4 (VAR 'b')
> > > >
> > > > There are two issues that I hit:
> > > >
> > > > 1. The component_idx=-1 makes it a little inconvenient to correlate
> > > > the tag applied to a VAR in a DATASEC. In case of structs the index
> > > > can be matched with component_idx, in case of DATASEC we have to match
> > > > VAR's type_id. So the code has to be different. If it also had
> > > > component_idx set it would be possible to make the code same for both
> > > > inside the kernel's field parsing routine.
> > >
> > > This is expected and documented in UAPI:
> > >
> > >   "If component_idx == -1, the tag is applied to a struct, union,
> > > variable or function."
> > >
> > > Variable is an independent entity and tag applies to it. I don't
> > > know/remember why we did it this way, but it's probably easier for
> > > Clang to generate it this way. And it probably is easier for BPF
> > > static linker as well. Note that you don't merge two structs together,
> > > while static linker does merge variables between DATASECs.
> > >
> > > In short, DATASEC+VAR is sufficiently different from STRUCT+fields, so
> > > is treated differently.
> > >
> >
> > I see, thanks. In that case I'll add this description as a comment
> > where the code matches the tag to the VAR.
> >
> > > >
> > > > 2. The second issue is that the offset is always 0 for DATASEC VARs.
> > > > That makes it difficult to ensure proper alignment of the variables.
> > >
> > > That's also expected (even if unfortunate) behavior of Clang. Good
> > > news is that libbpf's static linker API is normalizing this. Libbpf
> > > itself also normalizes it internally if passed .bpf.o file straight
> > > from Clang's output.
> > >
> > > In short, if you run `bpftool gen object my_normalized.bpf.o
> > > my_clang.bpf.o` you'll get offsets in my_normalized.bpf.o's BTF.
> > >
> >
> > I see. It would be better if this was fixed up by clang itself, but I
> > don't know enough about the BPF backend to comment whether that would
> > make sense.
> >
> > It's unlikely people will run it through libbpf's linker when they're
> > not statically linking more than one object (or even be using libbpf,
> > but that's a separate thing), and it's very hard to correlate the
> > errors to their cause when failure happens during MAP_CREATE (I guess
> > eventually it should support a log buffer like btf load and prog
> > load), so in the end it would be confusing for users.
> >
> > However we do need to ensure the offsets are correct to detect proper
> > alignment. So adding some checks looks inevitable.
> > I guess for the first VAR, we can assume offset==0 is fine, but from
> > the next VAR, we should return an error if we see offset==0 again?
> > This should catch the not normalized case in case of DATASEC vlen > 1
> > (== 1 should still be ok). wdyt?
> >
>
> It's unclear who's "we", who's loading what, when and where, tbh. So
> please provide a bit of a context. We started from a simple isolated C
> example and two questions about BTF, and now I'm not sure what we are
> talking about at all.
>
> Libbpf patches BTF and assigns correct offsets before loading BTF into
> the kernel. But I assume whatever you are doing doesn't use libbpf?
>

Sorry :), my bad. So this is about the bpf list series.

struct bpf_list_head head __contains(foo, node); // global variable
That 'contains' is a declaration tag.

In https://lore.kernel.org/bpf/20220904204145.3089-14-memxor@xxxxxxxxx

I was calling btf_find_list_head inside btf_find_datasec_var with
index == -1 (third argument) which is eventually matched with
component_idx in btf_find_decl_tag_value.

So that part is something you clarified, but earlier in
btf_find_datasec_var the code also checks the alignment using the
offset of the VAR.

What I was trying to say is that we cannot assume libbpf fixes up the
offsets for the map BTF inside the kernel, a user may load a
non-normalized BTF with all offsets of DATASEC VARs as 0, so we should
probably still reject seeing off == 0 after the first VAR in a
DATASEC, otherwise the off % align check can be bypassed.

Hopefully it's clearer now.

> > > >
> > > > I would like to know if these are expected behaviors or bugs?
> > >
> > > Features ;)
> > >
> > > > Thanks
> > > > --
> > > >  ; clang --version
> > > > Ubuntu clang version
> > > > 16.0.0-++20220813052912+eaf0aa1f1fbd-1~exp1~20220813173018.344



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux