Re: [PATCH pahole 0/3] several btf changes

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

 



Em Thu, Dec 20, 2018 at 11:14:48PM +0000, Yonghong Song escreveu:
> 
> 
> On 12/20/18 10:31 AM, Arnaldo Carvalho de Melo wrote:
> > Adding dwarves@xxxxxxxxxxxxxxx to the CC list.
> > 
> > Em Tue, Dec 18, 2018 at 02:09:38PM -0800, Yonghong Song escreveu:
> >> This patch set included three btf related changes.
> >   
> >> Patch #1 added support to do dwarf->btf conversion
> >>    for multiple cu's and multiple binaries.
> >> Patch #2 added support to generate types for struct,
> >>    union and fwd using kind_flag. The kernel support
> >>    for kind_flag is here:
> >>    https://urldefense.proofpoint.com/v2/url?u=https-3A__www.spinics.net_lists_netdev_msg539088.html&d=DwIBAg&c=5VD0RTtNlTh3ycd41b3MUw&r=DA8e1B5r073vIqRrFz7MRA&m=yUci7csgF5JQxbKJ-Qbe7_WSnzpZGNHBeR9v6sbfOX8&s=x1n4q5bAFOwgK8gMbeRHbtQ-PEXqurdDjCkhEjY-d6s&e=
> >> Patch #3 added func_proto support. The kernel support
> >>    is here:
> >>    https://urldefense.proofpoint.com/v2/url?u=https-3A__www.spinics.net_lists_netdev_msg534643.html&d=DwIBAg&c=5VD0RTtNlTh3ycd41b3MUw&r=DA8e1B5r073vIqRrFz7MRA&m=yUci7csgF5JQxbKJ-Qbe7_WSnzpZGNHBeR9v6sbfOX8&s=BLITwXmBAnM1RkuzWM9DFwGNw1YPlZArh7qR9OY-Azc&e=
> >   
> >> Please see individual patch for details.
> >   
> >> Yonghong Song (3):
> >>    btf: permit multiple cu's for dwarf->btf conversion
> >>    btf: fix struct/union/fwd types with kind_flag
> >>    btf: add func_proto support
> > 
> > Ok, I tested and processed those and added a few more, adding a btf
> > loader, pushed out to my git.kernel.org pahole repo.
> > 
> > The btf loader is at:
> > 
> >    https://git.kernel.org/pub/scm/devel/pahole/pahole.git/commit/?id=472256d3c57bef53250686d55bd011f5dab4b657
> > 
> > Please take a look to see if I made some mistake.
> 
> I looked at this issue. The reason is you did not take into the 
> consideration of recent kind_flag. Basically, bitfield_size can be

oops, thanks for the quick review+fix

> determined without looking at member types.
>     if (kind_flag)
>        bitfield_size = BTF_MEMBER_BITFIELD_SIZE(offset)
>     else
>        bitfield_size = 0
> 
> I will send a separate patch to address this issue. Feel free to reuse
> any part of it if you need more changes.
> 
> > 
> > For a net/ipv4/tcp.o from a kernel build, for struct sk_buff, shows
> > differences wrt the bit size of bitfield members, that is not encoded in
> > BTF at the moment:
> > 
> >    $ pahole -F btf -C sk_buff ~/git/build/v4.20-rc5+/net/ipv4/tcp.o > /tmp/sk_buff.btf
> >    $ pahole -F dwarf -C sk_buff ~/git/build/v4.20-rc5+/net/ipv4/tcp.o > /tmp/sk_buff.dwarf
> >    $ diff -u /tmp/sk_buff.dwarf /tmp/sk_buff.btf
> >    --- /tmp/sk_buff.dwarf	2018-12-20 14:50:51.428653046 -0300
> >    +++ /tmp/sk_buff.btf	2018-12-20 14:50:46.302601516 -0300
> >    @@ -38,45 +38,45 @@
> >     	__u16                      hdr_len;              /*   138     2 */
> >     	__u16                      queue_mapping;        /*   140     2 */
> >     	__u8                       __cloned_offset[0];   /*   142     0 */
> >    -	__u8                       cloned:1;             /*   142: 7  1 */
> >    -	__u8                       nohdr:1;              /*   142: 6  1 */
> >    -	__u8                       fclone:2;             /*   142: 4  1 */
> >    -	__u8                       peeked:1;             /*   142: 3  1 */
> >    -	__u8                       head_frag:1;          /*   142: 2  1 */
> >    -	__u8                       xmit_more:1;          /*   142: 1  1 */
> >    -	__u8                       pfmemalloc:1;         /*   142: 0  1 */
> >    +	__u8                       cloned;               /*   142     1 */
> >    +	__u8                       nohdr;                /*   142     1 */
> >    +	__u8                       fclone;               /*   142     1 */
> >    +	__u8                       peeked;               /*   142     1 */
> >    +	__u8                       head_frag;            /*   142     1 */
> >    +	__u8                       xmit_more;            /*   142     1 */
> >    +	__u8                       pfmemalloc;           /*   142     1 */
> 
> With fixed btf loader, I got
> 
>          /* --- cacheline 2 boundary (128 bytes) --- */
>          __u16                      mac_len;              /*   128     2 */
>          __u16                      hdr_len;              /*   130     2 */
>          __u16                      queue_mapping;        /*   132     2 */
>          __u8                       __cloned_offset[0];   /*   134     0 */
>          __u8                       cloned:1;             /*   134: 0  1 */
>          __u8                       nohdr:1;              /*   134: 1  1 */
>          __u8                       fclone:2;             /*   134: 2  1 */
>          __u8                       peeked:1;             /*   134: 4  1 */
>          __u8                       head_frag:1;          /*   134: 5  1 */
>          __u8                       xmit_more:1;          /*   134: 6  1 */
>          __u8                       pfmemalloc:1;         /*   134: 7  1 */
> 
>          /* XXX 1 byte hole, try to pack */
> 
>          __u32                      headers_start[0];     /*   136     0 */
>          __u8                       __pkt_type_offset[0]; /*   136     0 */
>          __u8                       pkt_type:3;           /*   136: 0  1 */
>          __u8                       ignore_df:1;          /*   136: 3  1 */
>          __u8                       nf_trace:1;           /*   136: 4  1 */
>          __u8                       ip_summed:2;          /*   136: 5  1 */
>          __u8                       ooo_okay:1;           /*   136: 7  1 */
>          __u8                       l4_hash:1;            /*   137: 0  1 */
>          __u8                       sw_hash:1;            /*   137: 1  1 */
> 
> Ignore the byte offset which may due to different kernel configurations.
> The bitfield offset in BTF starts from lower number to bigger one. That 
> is, it is always following the big endian convention, bitfield_offset 
> will be smaller if close to the top of structure.
> 
> This is different from what dwarf is doing, which will show different 
> things on little endian vs. big endian.
> 
> You can make simple adjustment based on all available info. In 
> btf_encoder.s, we did similar adjustment for little endian from
> dwarf to btf.

Ok, will fix
 
> >     
> >     	/* XXX 1 byte hole, try to pack */
> >     
> >     	__u32                      headers_start[0];     /*   144     0 */
> >     	__u8                       __pkt_type_offset[0]; /*   144     0 */
> >    -	__u8                       pkt_type:3;           /*   144: 5  1 */
> >    -	__u8                       ignore_df:1;          /*   144: 4  1 */
> >    -	__u8                       nf_trace:1;           /*   144: 3  1 */
> >    -	__u8                       ip_summed:2;          /*   144: 1  1 */
> >    -	__u8                       ooo_okay:1;           /*   144: 0  1 */
> >    -	__u8                       l4_hash:1;            /*   145: 7  1 */
> >    -	__u8                       sw_hash:1;            /*   145: 6  1 */
> >    -	__u8                       wifi_acked_valid:1;   /*   145: 5  1 */
> >    -	__u8                       wifi_acked:1;         /*   145: 4  1 */
> >    -	__u8                       no_fcs:1;             /*   145: 3  1 */
> >    -	__u8                       encapsulation:1;      /*   145: 2  1 */
> >    -	__u8                       encap_hdr_csum:1;     /*   145: 1  1 */
> >    -	__u8                       csum_valid:1;         /*   145: 0  1 */
> >    -	__u8                       csum_complete_sw:1;   /*   146: 7  1 */
> >    -	__u8                       csum_level:2;         /*   146: 5  1 */
> >    -	__u8                       csum_not_inet:1;      /*   146: 4  1 */
> >    -	__u8                       dst_pending_confirm:1; /*   146: 3  1 */
> >    -	__u8                       ndisc_nodetype:2;     /*   146: 1  1 */
> >    -	__u8                       ipvs_property:1;      /*   146: 0  1 */
> >    -	__u8                       inner_protocol_type:1; /*   147: 7  1 */
> >    -	__u8                       remcsum_offload:1;    /*   147: 6  1 */
> >    -	__u8                       offload_fwd_mark:1;   /*   147: 5  1 */
> >    -	__u8                       offload_mr_fwd_mark:1; /*   147: 4  1 */
> >    -	__u8                       tc_skip_classify:1;   /*   147: 3  1 */
> >    -	__u8                       tc_at_ingress:1;      /*   147: 2  1 */
> >    -	__u8                       tc_redirected:1;      /*   147: 1  1 */
> >    -	__u8                       tc_from_ingress:1;    /*   147: 0  1 */
> >    +	__u8                       pkt_type;             /*   144     1 */
> >    +	__u8                       ignore_df;            /*   144     1 */
> >    +	__u8                       nf_trace;             /*   144     1 */
> >    +	__u8                       ip_summed;            /*   144     1 */
> >    +	__u8                       ooo_okay;             /*   144     1 */
> >    +	__u8                       l4_hash;              /*   145     1 */
> >    +	__u8                       sw_hash;              /*   145     1 */
> >    +	__u8                       wifi_acked_valid;     /*   145     1 */
> >    +	__u8                       wifi_acked;           /*   145     1 */
> >    +	__u8                       no_fcs;               /*   145     1 */
> >    +	__u8                       encapsulation;        /*   145     1 */
> >    +	__u8                       encap_hdr_csum;       /*   145     1 */
> >    +	__u8                       csum_valid;           /*   145     1 */
> >    +	__u8                       csum_complete_sw;     /*   146     1 */
> >    +	__u8                       csum_level;           /*   146     1 */
> >    +	__u8                       csum_not_inet;        /*   146     1 */
> >    +	__u8                       dst_pending_confirm;  /*   146     1 */
> >    +	__u8                       ndisc_nodetype;       /*   146     1 */
> >    +	__u8                       ipvs_property;        /*   146     1 */
> >    +	__u8                       inner_protocol_type;  /*   147     1 */
> >    +	__u8                       remcsum_offload;      /*   147     1 */
> >    +	__u8                       offload_fwd_mark;     /*   147     1 */
> >    +	__u8                       offload_mr_fwd_mark;  /*   147     1 */
> >    +	__u8                       tc_skip_classify;     /*   147     1 */
> >    +	__u8                       tc_at_ingress;        /*   147     1 */
> >    +	__u8                       tc_redirected;        /*   147     1 */
> >    +	__u8                       tc_from_ingress;      /*   147     1 */
> >     	__u16                      tc_index;             /*   148     2 */
> >     
> >     	/* XXX 2 bytes hole, try to pack */
> >    $
> > 
> > For the whole net/ipv6/tcp.o:
> > 
> > I'm getting a segfault when processing this entry:
> > 
> > [acme@quaco pahole]$ pahole -F dwarf -C fpregs_state ~/git/build/v4.20-rc5+/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 */
> > };
> > [acme@quaco pahole]$
> > 
> > [acme@quaco pahole]$ pahole -F btf -C fpregs_state ~/git/build/v4.20-rc5+/net/ipv4/tcp.o
> > Segmentation fault (core dumped)
> > [acme@quaco pahole]$
> 
> I can easily reproduce with the following simple file.
> -bash-4.4$ cat t.c
> union t {
>    int a;
>    int b;
> } g;
> 
> Looks like the call chain likes
>    print_classes
>      cu__for_each_struct_or_union(cu, id, pos) {
>          ....
>          class__filter(...)
> 
> But in btf_loader.c, struct is allocated with class__new(), but union is
> allocated with type__new(). Maybe some issue here?

Will investigate.
 
> > 
> > Have to stop now, will try to fix this later, please let me know if you
> > found the problem meanwhile :-)
> > 
> > The difference up to the point where it tries to process that union is
> > just related to bitfields:
> > 
> > --- /tmp/tcp.o.dwarf.c	2018-12-20 15:00:09.249222711 -0300
> > +++ /tmp/tcp.o.btf.c	2018-12-20 15:22:00.935246130 -0300
> > @@ -81,11 +81,13 @@
> >   	const char  *              function;             /*     8     8 */
> >   	const char  *              filename;             /*    16     8 */
> >   	const char  *              format;               /*    24     8 */
> > -	unsigned int               lineno:18;            /*    32:14  4 */
> > -	unsigned int               flags:8;              /*    32: 6  4 */
> > +	unsigned int               lineno;               /*    32     4 */
> >   
> > -	/* XXX 6 bits hole, try to pack */
> > -	/* XXX 4 bytes hole, try to pack */
> > +	/* Bitfield combined with next fields */
> > +
> > +	unsigned int               flags;                /*    34     4 */
> > +
> > +	/* XXX 2 bytes hole, try to pack */
> >   
> >   	union {
> >   		struct static_key_true dd_key_true;      /*    40    16 */
> > @@ -93,8 +95,7 @@
> >   	} key;                                           /*    40    16 */
> >   
> >   	/* size: 56, cachelines: 1, members: 7 */
> > -	/* sum members: 52, holes: 1, sum holes: 4 */
> > -	/* bit holes: 1, sum bit holes: 6 bits */
> > +	/* sum members: 54, holes: 1, sum holes: 2 */
> >   	/* last cacheline: 56 bytes */
> >   };
> >   struct file_operations {
> > @@ -223,7 +224,11 @@
> >   		} futex;                                 /*     8    40 */
> >   		struct {
> >   			clockid_t  clockid;              /*     8     4 */
> > -			enum timespec_type type;         /*    12     4 */
> > +			enum timespec_type type:4;       /*    12: 0  1 */
> > +
> > +			/* XXX 4 bits hole, try to pack */
> > +			/* XXX 3 bytes hole, try to pack */
> > +
> >   			union {
> >   				struct timespec * rmtp;  /*    16     8 */
> >   				struct old_timespec32 * compat_rmtp; /*    16     8 */
> > @@ -320,22 +325,16 @@
> >   
> >   	long unsigned int          jobctl;               /*  1120     8 */
> >   	unsigned int               personality;          /*  1128     4 */
> > -	unsigned int               sched_reset_on_fork:1; /*  1132:31  4 */
> > -	unsigned int               sched_contributes_to_load:1; /*  1132:30  4 */
> > -	unsigned int               sched_migrated:1;     /*  1132:29  4 */
> > -	unsigned int               sched_remote_wakeup:1; /*  1132:28  4 */
> > -
> > -	/* XXX 28 bits hole, try to pack */
> > -
> > -	unsigned int               in_execve:1;          /*  1136:31  4 */
> > -	unsigned int               in_iowait:1;          /*  1136:30  4 */
> > -	unsigned int               restore_sigmask:1;    /*  1136:29  4 */
> > -	unsigned int               in_user_fault:1;      /*  1136:28  4 */
> > -	unsigned int               no_cgroup_migration:1; /*  1136:27  4 */
> > -	unsigned int               use_memdelay:1;       /*  1136:26  4 */
> > -
> > -	/* XXX 26 bits hole, try to pack */
> > -
> > +	unsigned int               sched_reset_on_fork;  /*  1132     4 */
> > +	unsigned int               sched_contributes_to_load; /*  1132     4 */
> > +	unsigned int               sched_migrated;       /*  1132     4 */
> > +	unsigned int               sched_remote_wakeup;  /*  1132     4 */
> > +	unsigned int               in_execve;            /*  1136     4 */
> > +	unsigned int               in_iowait;            /*  1136     4 */
> > +	unsigned int               restore_sigmask;      /*  1136     4 */
> > +	unsigned int               in_user_fault;        /*  1136     4 */
> > +	unsigned int               no_cgroup_migration;  /*  1136     4 */
> > +	unsigned int               use_memdelay;         /*  1136     4 */
> >   	unsigned int               kernel_uaccess_faults_ok; /*  1140     4 */
> >   	long unsigned int          atomic_flags;         /*  1144     8 */
> >   	/* --- cacheline 18 boundary (1152 bytes) --- */
> > @@ -548,7 +547,6 @@
> >   
> >   	/* size: 11008, cachelines: 172, members: 207 */
> >   	/* sum members: 10906, holes: 15, sum holes: 102 */
> > -	/* bit holes: 2, sum bit holes: 54 bits */
> >   	/* paddings: 3, sum paddings: 14 */
> >   };
> >   struct screen_info {
> > @@ -811,40 +809,64 @@
> >   struct desc_struct {
> >   	u16                        limit0;               /*     0     2 */
> >   	u16                        base0;                /*     2     2 */
> > -	u16                        base1:8;              /*     4: 8  2 */
> > -	u16                        type:4;               /*     4: 4  2 */
> > -	u16                        s:1;                  /*     4: 3  2 */
> > -	u16                        dpl:2;                /*     4: 1  2 */
> > -	u16                        p:1;                  /*     4: 0  2 */
> > -	u16                        limit1:4;             /*     6:12  2 */
> > -	u16                        avl:1;                /*     6:11  2 */
> > -	u16                        l:1;                  /*     6:10  2 */
> > -	u16                        d:1;                  /*     6: 9  2 */
> > -	u16                        g:1;                  /*     6: 8  2 */
> > -	u16                        base2:8;              /*     6: 0  2 */
> > +	u16                        base1;                /*     4     2 */
> > +
> > +	/* Bitfield combined with next fields */
> > +
> > +	u16                        type;                 /*     5     2 */
> > +	u16                        s;                    /*     5     2 */
> > +	u16                        dpl;                  /*     5     2 */
> > +	u16                        p;                    /*     5     2 */
> > +
> > +	/* Bitfield combined with next fields */
> > +
> > +	u16                        limit1;               /*     6     2 */
> > +	u16                        avl;                  /*     6     2 */
> > +	u16                        l;                    /*     6     2 */
> > +	u16                        d;                    /*     6     2 */
> > +	u16                        g;                    /*     6     2 */
> > +
> > +	/* Bitfield combined with next fields */
> > +
> > +	u16                        base2;                /*     7     2 */
> >   
> >   	/* size: 8, cachelines: 1, members: 13 */
> > +	/* padding: 65535 */
> >   	/* last cacheline: 8 bytes */
> > +
> > +	/* BRAIN FART ALERT! 8 != 9 + 0(holes), diff = -1 */
> > +
> >   };
> >   struct idt_bits {
> > -	u16                        ist:3;                /*     0:13  2 */
> > -	u16                        zero:5;               /*     0: 8  2 */
> > -	u16                        type:5;               /*     0: 3  2 */
> > -	u16                        dpl:2;                /*     0: 1  2 */
> > -	u16                        p:1;                  /*     0: 0  2 */
> > +	u16                        ist;                  /*     0     2 */
> > +	u16                        zero;                 /*     0     2 */
> > +
> > +	/* Bitfield combined with next fields */
> > +
> > +	u16                        type;                 /*     1     2 */
> > +	u16                        dpl;                  /*     1     2 */
> > +	u16                        p;                    /*     1     2 */
> >   
> >   	/* size: 2, cachelines: 1, members: 5 */
> > +	/* padding: 65535 */
> >   	/* last cacheline: 2 bytes */
> > +
> > +	/* BRAIN FART ALERT! 2 != 3 + 0(holes), diff = -1 */
> > +
> >   };
> >   struct gate_struct {
> >   	u16                        offset_low;           /*     0     2 */
> >   	u16                        segment;              /*     2     2 */
> >   	struct idt_bits            bits;                 /*     4     2 */
> > +
> > +	/* XXX last struct has 65535 bytes of padding */
> > +
> >   	u16                        offset_middle;        /*     6     2 */
> >   	u32                        offset_high;          /*     8     4 */
> >   	u32                        reserved;             /*    12     4 */
> >   
> >   	/* size: 16, cachelines: 1, members: 6 */
> > +	/* paddings: 1, sum paddings: 65535 */
> >   	/* last cacheline: 16 bytes */
> >   };
> >   struct desc_ptr {
> > @@ -884,9 +906,15 @@
> >   				void * s_mem;            /*    40     8 */
> >   				long unsigned int counters; /*    40     8 */
> >   				struct {
> > -					unsigned int inuse:16; /*    40:16  4 */
> > -					unsigned int objects:15; /*    40: 1  4 */
> > -					unsigned int frozen:1; /*    40: 0  4 */
> > +					unsigned int inuse; /*    40     4 */
> > +
> > +					/* Bitfield combined with next fields */
> > +
> > +					unsigned int objects; /*    42     4 */
> > +
> > +					/* Bitfield combined with next fields */
> > +
> > +					unsigned int frozen; /*    43     4 */
> >   				};                       /*    40     4 */
> >   			};                               /*    40     8 */
> >   		};                                       /*     8    40 */
> > @@ -1039,10 +1067,9 @@
> >   	/* XXX 4 bytes hole, try to pack */
> >   
> >   	mm_segment_t               addr_limit;           /*   152     8 */
> > -	unsigned int               sig_on_uaccess_err:1; /*   160:31  4 */
> > -	unsigned int               uaccess_err:1;        /*   160:30  4 */
> > +	unsigned int               sig_on_uaccess_err;   /*   160     4 */
> > +	unsigned int               uaccess_err;          /*   160     4 */
> >   
> > -	/* XXX 30 bits hole, try to pack */
> >   	/* XXX 28 bytes hole, try to pack */
> >   
> >   	/* --- cacheline 3 boundary (192 bytes) --- */
> > @@ -1050,7 +1077,6 @@
> >   
> >   	/* size: 4352, cachelines: 68, members: 21 */
> >   	/* sum members: 4320, holes: 2, sum holes: 32 */
> > -	/* bit holes: 1, sum bit holes: 30 bits */
> >   };
> >   struct pv_irq_ops {
> >   	struct paravirt_callee_save save_fl;             /*     0     8 */
> > 

-- 

- Arnaldo



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

  Powered by Linux