Re: [PATCH pahole] btf_loader: Fix loading union types in BTF loader

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

 



On Thu, Jan 10, 2019 at 5:06 AM Arnaldo Carvalho de Melo
<acme@xxxxxxxxxx> wrote:
>
> Em Mon, Dec 31, 2018 at 06:03:27AM +0000, Andrii Nakryiko escreveu:
> > Union, when loaded, were created as 'struct type', while structs were
> > created as 'struct class', that contained 'struct type' within it. When
> > processing, though, unions and structs were treated the same with
> > assumption that they both are represented by 'struct class'. This patch
> > fixes issue by making sure unions and structs are created the same,
> > modulo DW_TAG_structure_type vs DW_TAG_union_type tag.
> >
> > Without fix:
> >
> >   andriin@devvm$ ~/local/pahole/build/pahole -F dwarf -C fpregs_state ~/local/linux/net/ipv4/tcp.o
> >   union fpregs_state {
> >           struct fxregs_state        fxsave;             /*     0   512 */
> >           struct swregs_state        soft;               /*     0   136 */
> >           struct xregs_state         xsave;              /*     0   576 */
> >           u8                         __padding[4096];    /*     0  4096 */
> >   };
> >   andriin@devvm$ ~/local/pahole/build/pahole -F btf -C fpregs_state ~/local/linux/net/ipv4/tcp.o
> >   Segmentation fault (core dumped)
>
> I couldn't reproduce this here:
>
> [acme@quaco pahole]$ pahole -J ~/git/build/v4.20-rc5/net/ipv4/tcp.o
> [acme@quaco pahole]$ pahole -F btf -C fpregs_state ~/git/build/v4.20-rc5/net/ipv4/tcp.o
> union fpregs_state {
>         struct fregs_state         fsave;              /*     0   112 */
>         struct fxregs_state        fxsave;             /*     0   512 */
>         struct swregs_state        soft;               /*     0   136 */
>         struct xregs_state         xsave;              /*     0   576 */
>         u8                         __padding[4096];    /*     0  4096 */
> };
> [acme@quaco pahole]$
>
> Can you try with what in my current tree? I think these address it:

Yes, you are right, your changes fixed the issue for both BTF and DWARF.
Please disregard the other patch I've sent for dwarf_encoder as well
([PATCH pahole] dwarf_loader: Represent union in same way as struct).

>
> e066ed0431b6 (HEAD -> master, acme.korg/master) pahole: Fix logic inversion wrt finding holes in structs
> 6ebb50f47b19 pahole: Do not apply 'struct class' filters to 'struct type'
> c9afdf88411d dwarves: Check if the tag is a 'struct class' in class__find_holes()
>
> And I merged 6ebb50f47b19  with e066ed0431b6 to preserve bisectability.
>
> So update the branch and this is the fix:
>
> commit 2c4569a952e0910a4a19d87d636f0887f5f7ed4d
> Author: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
> Date:   Fri Dec 21 14:20:58 2018 -0300
>
>     pahole: Do not apply 'struct class' filters to 'struct type'
>
>     Now unions are handled as well in pahole, so bail out before checking
>     'struct class' members for struct specific filters when handling
>     non-structs in class__filter()
>
>     Fixes: 31664d60ad41 ("pahole: Show tagged enums as well when no class is specified")
>     Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
>
>
> - Arnaldo
>
> >
> > With fix:
> >
> >   andriin@devvm$ ~/local/pahole/build/pahole -F dwarf -C fpregs_state ~/local/linux/net/ipv4/tcp.o
> >   union fpregs_state {
> >           struct fxregs_state        fxsave;             /*     0   512 */
> >           struct swregs_state        soft;               /*     0   136 */
> >           struct xregs_state         xsave;              /*     0   576 */
> >           u8                         __padding[4096];    /*     0  4096 */
> >   };
> >   andriin@devvm$ ~/local/pahole/build/pahole -F btf -C fpregs_state ~/local/linux/net/ipv4/tcp.o
> >   union fpregs_state {
> >           struct fregs_state         fsave;              /*     0   112 */
> >           struct fxregs_state        fxsave;             /*     0   512 */
> >           struct swregs_state        soft;               /*     0   136 */
> >           struct xregs_state         xsave;              /*     0   576 */
> >           u8                         __padding[4096];    /*     0  4096 */
> >   };
> >
> > Note that there is a difference between DWARF and BTF loader outputs:
> > DWARF one seems to always skip first member of union type. It's not the case
> > for structs, though. This issue will be investigated and fixed separately.
> >
> > Signed-off-by: Andrii Nakryiko <andriin@xxxxxx>
> > ---
> >  btf_loader.c | 39 ++++++++++++---------------------------
> >  1 file changed, 12 insertions(+), 27 deletions(-)
> >
> > diff --git a/btf_loader.c b/btf_loader.c
> > index dae21d5..f04b12a 100644
> > --- a/btf_loader.c
> > +++ b/btf_loader.c
> > @@ -1,4 +1,4 @@
> > -/*
> > +/*
> >   * btf_loader.c
> >   *
> >   * Copyright (C) 2018 Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
> > @@ -121,12 +121,12 @@ static struct type *type__new(uint16_t tag, strings_t name, size_t size)
> >       return type;
> >  }
> >
> > -static struct class *class__new(strings_t name, size_t size)
> > +static struct class *class__new(strings_t name, size_t size, uint16_t tag)
> >  {
> >       struct class *class = tag__alloc(sizeof(*class));
> >
> >       if (class != NULL) {
> > -             type__init(&class->type, DW_TAG_structure_type, name, size);
> > +             type__init(&class->type, tag, name, size);
> >               INIT_LIST_HEAD(&class->vtable);
> >       }
> >
> > @@ -205,7 +205,10 @@ static int create_members(struct btf *btf, void *ptr, int vlen, struct type *cla
> >  static int create_new_class(struct btf *btf, void *ptr, int vlen, struct btf_type *tp, uint64_t size, long id)
> >  {
> >       strings_t name = btf__get32(btf, &tp->name_off);
> > -     struct class *class = class__new(name, size);
> > +     uint16_t type_tag = BTF_INFO_KIND(tp->info) == BTF_KIND_STRUCT
> > +             ? DW_TAG_structure_type
> > +             : DW_TAG_union_type;
> > +     struct class *class = class__new(name, size, type_tag);
> >       int member_size = create_members(btf, ptr, vlen, &class->type);
> >
> >       if (member_size < 0)
> > @@ -219,25 +222,6 @@ out_free:
> >       return -ENOMEM;
> >  }
> >
> > -static int create_new_union(struct btf *btf, void *ptr,
> > -                         int vlen, struct btf_type *tp,
> > -                         uint64_t size, long id)
> > -{
> > -     strings_t name = btf__get32(btf, &tp->name_off);
> > -     struct type *un = type__new(DW_TAG_union_type, name, size);
> > -     int member_size = create_members(btf, ptr, vlen, un);
> > -
> > -     if (member_size < 0)
> > -             goto out_free;
> > -
> > -     cu__add_tag(btf->priv, &un->namespace.tag, &id);
> > -
> > -     return (vlen * member_size);
> > -out_free:
> > -     type__delete(un, btf->priv);
> > -     return -ENOMEM;
> > -}
> > -
> >  static struct enumerator *enumerator__new(strings_t name, uint32_t value)
> >  {
> >       struct enumerator *en = tag__alloc(sizeof(*en));
> > @@ -302,7 +286,10 @@ static int create_new_subroutine_type(struct btf *btf, void *ptr,
> >  static int create_new_forward_decl(struct btf *btf, struct btf_type *tp, uint64_t size, long id)
> >  {
> >       strings_t name = btf__get32(btf, &tp->name_off);
> > -     struct class *fwd = class__new(name, size);
> > +     uint16_t type_tag = BTF_INFO_KIND(tp->info)
> > +             ? DW_TAG_union_type
> > +             : DW_TAG_structure_type;
> > +     struct class *fwd = class__new(name, size, type_tag);
> >
> >       if (fwd == NULL)
> >               return -ENOMEM;
> > @@ -384,10 +371,8 @@ static int btf__load_types(struct btf *btf)
> >                       vlen = create_new_base_type(btf, ptr, type_ptr, type_index);
> >               } else if (type == BTF_KIND_ARRAY) {
> >                       vlen = create_new_array(btf, ptr, type_index);
> > -             } else if (type == BTF_KIND_STRUCT) {
> > +             } else if (type == BTF_KIND_STRUCT || type == BTF_KIND_UNION) {
> >                       vlen = create_new_class(btf, ptr, vlen, type_ptr, size, type_index);
> > -             } else if (type == BTF_KIND_UNION) {
> > -                     vlen = create_new_union(btf, ptr, vlen, type_ptr, size, type_index);
> >               } else if (type == BTF_KIND_ENUM) {
> >                       vlen = create_new_enumeration(btf, ptr, vlen, type_ptr, size, type_index);
> >               } else if (type == BTF_KIND_FWD) {
> > --
> > 2.17.1
>
> --
>
> - Arnaldo



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux