1. 23 Sep, 2019 1 commit
  2. 18 Sep, 2019 1 commit
  3. 17 Sep, 2019 1 commit
  4. 12 Sep, 2019 3 commits
  5. 30 Jul, 2019 2 commits
  6. 28 Jul, 2019 3 commits
  7. 27 Jun, 2019 1 commit
  8. 14 May, 2019 1 commit
  9. 01 May, 2019 2 commits
  10. 23 Apr, 2019 4 commits
  11. 16 Apr, 2019 10 commits
    • Arnaldo Carvalho de Melo's avatar
      MANIFEST: Add missing files to generate the tarball · 8288d884
      Arnaldo Carvalho de Melo authored
      btf_loader.c and the libbpf obtained via the git module are needed to
      be able to build from the tarball generated via:
      
        tar cvfj rpm/SOURCES/dwarves-1.13.tar.bz2 `cat MANIFEST`
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      8288d884
    • Arnaldo Carvalho de Melo's avatar
      v1.13: New release · 92a41188
      Arnaldo Carvalho de Melo authored
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      92a41188
    • Arnaldo Carvalho de Melo's avatar
      pfunct: Strip inlines in the code generated for --compile · 0fb72716
      Arnaldo Carvalho de Melo authored
      If we have:
      
      inline void process_adjtimex_modes(const struct __kernel_timex  * txc, s32 * time_tai)
      {
      }
      
      And any other struct receiving as a parameter pointers to 'struct
      __kerne_timex', then the source file with the above inline, since it
      doesn't have any inline expansion, i.e. 'pfunct --compile' generates
      just empty function bodies, the types won't be included in the resulting
      .o.
      
      Since the original file has the expansions, type types will be there and
      thus we will not be able to compare those types, so ask for any 'inline'
      to be stripped, so that we keep those types and 'fullcircle' can do its
      work.
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      0fb72716
    • Arnaldo Carvalho de Melo's avatar
      emit: Emit the types for inline structs defined in pointer members · 7b967744
      Arnaldo Carvalho de Melo authored
      I.e. before:
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/block/partitions/sgi.o > a.c
          $ gcc -g -c a.c
        a.c:9:3: error: unknown type name ‘sector_t’
           sector_t           from;                 /*     0     8 */
           ^~~~~~~~
        a.c:10:3: error: unknown type name ‘sector_t’
           sector_t           size;                 /*     8     8 */
           ^~~~~~~~
        a.c:13:30: error: field ‘info’ has incomplete type
           struct partition_meta_info info;         /*    21   101 */
                                      ^~~~
        $
      
      After:
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/block/partitions/sgi.o > a.c
        $ gcc -g -c a.c
        $ head -40 a.c
        struct block_device;
      
        typedef long unsigned int sector_t;
      
        typedef _Bool bool;
      
        typedef unsigned char __u8;
        typedef __u8 u8;
      
        struct partition_meta_info {
        	char                       uuid[37];             /*     0    37 */
        	u8                         volname[64];          /*    37    64 */
      
        	/* size: 101, cachelines: 2, members: 2 */
        	/* last cacheline: 37 bytes */
        };
      
        struct parsed_partitions {
        	struct block_device * bdev;                      /*     0     8 */
        	char                       name[32];             /*     8    32 */
        	struct {
        		sector_t           from;                 /*     0     8 */
        		sector_t           size;                 /*     8     8 */
        		int                flags;                /*    16     4 */
        		bool               has_info;             /*    20     1 */
        		struct partition_meta_info info;         /*    21   101 */
        	} * parts; /*    40     8 */
        	int                        next;                 /*    48     4 */
        	int                        limit;                /*    52     4 */
        	bool                       access_beyond_eod;    /*    56     1 */
      
        	/* XXX 7 bytes hole, try to pack */
      
        	/* --- cacheline 1 boundary (64 bytes) --- */
        	char *                     pp_buf;               /*    64     8 */
      
        	/* size: 72, cachelines: 2, members: 7 */
        	/* sum members: 65, holes: 1, sum holes: 7 */
        	/* last cacheline: 8 bytes */
        };
        $
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      7b967744
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Print relative offsets for inner pointer structs · 30526e28
      Arnaldo Carvalho de Melo authored
      I.e. before:
      
            $ pahole -C parsed_partitions /home/acme/git/build/v5.1-rc4+/block/partitions/check.o > a.c ; head -29 a.c
            struct parsed_partitions {
                  struct block_device * bdev;                      /*     0     8 */
                  char                       name[32];             /*     8    32 */
                  struct {
                          sector_t           from;                 /*    40     8 */
                          sector_t           size;                 /*    48     8 */
                          int                flags;                /*    56     4 */
                          bool               has_info;             /*    60     1 */
                          struct partition_meta_info info;         /*    61   101 */
                  } * parts; /*    40     8 */
                  int                        next;                 /*    48     4 */
                  int                        limit;                /*    52     4 */
                  bool                       access_beyond_eod;    /*    56     1 */
      
                  /* XXX 7 bytes hole, try to pack */
      
                  /* --- cacheline 1 boundary (64 bytes) --- */
                  char *                     pp_buf;               /*    64     8 */
      
                  /* size: 72, cachelines: 2, members: 7 */
                  /* sum members: 65, holes: 1, sum holes: 7 */
                  /* last cacheline: 8 bytes */
            };
            $
      
      Now:
      
        $ pahole -C parsed_partitions /home/acme/git/build/v5.1-rc4+/block/partitions/check.o
        struct parsed_partitions {
        	struct block_device * bdev;                      /*     0     8 */
        	char                       name[32];             /*     8    32 */
        	struct {
        		sector_t           from;                 /*     0     8 */
        		sector_t           size;                 /*     8     8 */
        		int                flags;                /*    16     4 */
        		bool               has_info;             /*    20     1 */
        		struct partition_meta_info info;         /*    21   101 */
        	} * parts; /*    40     8 */
        	int                        next;                 /*    48     4 */
        	int                        limit;                /*    52     4 */
        	bool                       access_beyond_eod;    /*    56     1 */
      
        	/* XXX 7 bytes hole, try to pack */
      
        	/* --- cacheline 1 boundary (64 bytes) --- */
        	char *                     pp_buf;               /*    64     8 */
      
        	/* size: 72, cachelines: 2, members: 7 */
        	/* sum members: 65, holes: 1, sum holes: 7 */
        	/* last cacheline: 8 bytes */
        };
        $
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      30526e28
    • Arnaldo Carvalho de Melo's avatar
      emit: Do not emit a forward declararion to a nameless struct · cfa377c2
      Arnaldo Carvalho de Melo authored
      This was happening here:
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/block/partitions/check.o > a.c ; head -29 a.c
        struct block_device;
      
        struct (null);
      
        typedef _Bool bool;
      
        struct parsed_partitions {
        	struct block_device * bdev;                      /*     0     8 */
        	char                       name[32];             /*     8    32 */
        	struct {
        		sector_t           from;                 /*    40     8 */
        		sector_t           size;                 /*    48     8 */
        		int                flags;                /*    56     4 */
        		bool               has_info;             /*    60     1 */
        		struct partition_meta_info info;         /*    61   101 */
        	} * parts; /*    40     8 */
        	int                        next;                 /*    48     4 */
        	int                        limit;                /*    52     4 */
        	bool                       access_beyond_eod;    /*    56     1 */
      
        	/* XXX 7 bytes hole, try to pack */
      
        	/* --- cacheline 1 boundary (64 bytes) --- */
        	char *                     pp_buf;               /*    64     8 */
      
        	/* size: 72, cachelines: 2, members: 7 */
        	/* sum members: 65, holes: 1, sum holes: 7 */
        	/* last cacheline: 8 bytes */
        };
        $
      
      I.e. we saw a pointer to a struct, so all we need is a forward
      declaration for that function, right? Not if it is defined inline, so
      just don't emit the forward declaration if the struct name is NULL.
      
      Oops, the offsets in a struct defined inline and that the member is a
      pointer need to have its offset restarted from zero...
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      cfa377c2
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Pretty print struct members that are pointers to nameless structs · cf459ca1
      Arnaldo Carvalho de Melo authored
      I.e. to structs defined inside other structs, without a name:
      
      Before:
      
        $ pahole -C parsed_partitions /home/acme/git/build/v5.1-rc4+/block/partitions/check.o
        struct parsed_partitions {
        	struct block_device *      bdev;                 /*     0     8 */
        	char                       name[32];             /*     8    32 */
        	struct  *                  parts;                /*    40     8 */
        	int                        next;                 /*    48     4 */
        	int                        limit;                /*    52     4 */
        	bool                       access_beyond_eod;    /*    56     1 */
      
        	/* XXX 7 bytes hole, try to pack */
      
        	/* --- cacheline 1 boundary (64 bytes) --- */
        	char *                     pp_buf;               /*    64     8 */
      
        	/* size: 72, cachelines: 2, members: 7 */
        	/* sum members: 65, holes: 1, sum holes: 7 */
        	/* last cacheline: 8 bytes */
        };
        $
      
      After:
      
        $ pahole -C parsed_partitions /home/acme/git/build/v5.1-rc4+/block/partitions/check.o
        struct parsed_partitions {
        	struct block_device * bdev;                      /*     0     8 */
        	char                       name[32];             /*     8    32 */
        	struct {
        		sector_t           from;                 /*    40     8 */
        		sector_t           size;                 /*    48     8 */
        		int                flags;                /*    56     4 */
        		bool               has_info;             /*    60     1 */
        		struct partition_meta_info info;         /*    61   101 */
        	} * parts; /*    40     8 */
        	int                        next;                 /*    48     4 */
        	int                        limit;                /*    52     4 */
        	bool                       access_beyond_eod;    /*    56     1 */
      
        	/* XXX 7 bytes hole, try to pack */
      
        	/* --- cacheline 1 boundary (64 bytes) --- */
        	char *                     pp_buf;               /*    64     8 */
      
        	/* size: 72, cachelines: 2, members: 7 */
        	/* sum members: 65, holes: 1, sum holes: 7 */
        	/* last cacheline: 8 bytes */
        };
        $
      
      Still need to align that offsets, leave this for later.
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      cf459ca1
    • Arnaldo Carvalho de Melo's avatar
      pfunct: Emit definitions for pointers inside pointer to function args · 09ed2e78
      Arnaldo Carvalho de Melo authored
      When using --compile we were missing emitting the types for function
      arguments in function pointers arguments, i.e.:
      
      Before:
      
        /home/acme/git/build/v5.1-rc4+/kernel/events/core.o
        /tmp/fullcircle.CZeLch.c:3770:141: warning: ‘struct perf_output_handle’ declared inside parameter list will not be visible outside of this definition or declaration
         inline int __perf_event_output(struct perf_event * event, struct perf_sample_data * data, struct pt_regs * regs, int (*output_begin)(struct perf_output_handle *, struct perf_event *, unsigned int))
                                                                                                                                                     ^~~~~~~~~~~~~~~~~~
      
      After:
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/kernel/events/core.o > a.c
        $ gcc -g -c a.c
        $ grep -w perf_output_handle -m1 -A5 a.c
        struct perf_output_handle;
      
        inline int __perf_event_output(struct perf_event * event, struct perf_sample_data * data, struct pt_regs * regs, int (*output_begin)(struct perf_output_handle *, struct perf_event *, unsigned int))
        {
      	  return 0;
        }
        $
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      09ed2e78
    • Arnaldo Carvalho de Melo's avatar
      fullcircle: Check that we found the CFLAGS · e9fc2f64
      Arnaldo Carvalho de Melo authored
      So that we don't try to compile something that wasn't built with a
      CFLAGS or even gcc, like .o made from ASM files.
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      e9fc2f64
    • Arnaldo Carvalho de Melo's avatar
      emit: Handle typedefs that are a pointer to typedefs · 05921c47
      Arnaldo Carvalho de Melo authored
      Before:
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/kernel/sched/autogroup.o > a.c
        $ gcc -g -c a.c
        a.c:1656:9: error: unknown type name ‘__signalfn_t’
         typedef __signalfn_t * __sighandler_t;
                 ^~~~~~~~~~~~
        a.c:1658:9: error: unknown type name ‘__restorefn_t’
         typedef __restorefn_t * __sigrestore_t;
                 ^~~~~~~~~~~~~
        $
      
      After:
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/kernel/sched/autogroup.o > a.c
        $ gcc -g -c a.c
        $ egrep  '__(restore|signal)fn_t' -A10 a.c
        typedef void (__signalfn_t)(int);
        typedef __signalfn_t * __sighandler_t;
      
        typedef void (__restorefn_t)(void);
        typedef __restorefn_t * __sigrestore_t;
      
        struct sigaction {
      	  __sighandler_t             sa_handler;           /*     0     8 */
      	  long unsigned int          sa_flags;             /*     8     8 */
      	  __sigrestore_t             sa_restorer;          /*    16     8 */
      	  sigset_t                   sa_mask;              /*    24     8 */
      
      	  /* size: 32, cachelines: 1, members: 4 */
      	  /* last cacheline: 32 bytes */
        };
        $
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      05921c47
  12. 15 Apr, 2019 11 commits
    • Arnaldo Carvalho de Melo's avatar
      fullcircle: Try building from pfunct --compile and check types · 87af9839
      Arnaldo Carvalho de Melo authored
      With this and running like:
      
        $ find ~/git/build/v5.1-rc4+/fs/ -name "*.o" | grep -v .mod.o | \
      	while read obj ; do
      		echo $obj ;
      		fullcircle $obj ;
      	done
      
      The vast majority of the kernel single compilation unit objects get
      the source code for its function prototypes and types used rebuilt,
      recompiled and then the original DWARF can be compared with the one
      generated from the regenerated C code.
      
      More work needed, but should be a good start and has already helped to
      fix several issues, a reported in the previous csets.
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      87af9839
    • Arnaldo Carvalho de Melo's avatar
      pfunct: Fixup more return types · c7fd9cc1
      Arnaldo Carvalho de Melo authored
      Covering typedefs, unions.
      
      Fixes: 99750f24 ("pfunct: Generate a valid return type for the --compile bodies")
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      c7fd9cc1
    • Arnaldo Carvalho de Melo's avatar
      emit: Make find_fwd_decl a bit more robust · 56c50b8d
      Arnaldo Carvalho de Melo authored
      We need to dig deeper in some emit cases, but for now lets make this
      a bit more robust by checking if the types are unnamed.
      
      Things like:
      
      struct b {
      	struct {
      		int a;
      	};
      }
      
      This is well handled in the main fprintf routines, but its interaction
      with the emit routines need more work, lets at least remove the segfault
      and leave fixing this for good for v1.14.
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      56c50b8d
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Handle single zero sized array member structs · 2bcb01fc
      Arnaldo Carvalho de Melo authored
        /home/acme/git/build/v5.1-rc4+/fs/proc/kcore.o
        /tmp/fullcircle.Vnd2oz.c:788:29: error: flexible array member in a struct with no named members
          char                       x[];                  /*     0     0 */
      
      Original:
      
      include/linux/mmzone.h, line 109:
      
        /*
         * zone->lock and the zone lru_lock are two of the hottest locks in the kernel.
         * So add a wild amount of padding here to ensure that they fall into separate
         * cachelines.  There are very few zone structures in the machine, so space
         * consumption is not a concern here.
         */
        #if defined(CONFIG_SMP)
        struct zone_padding {
                char x[0];
        } ____cacheline_internodealigned_in_smp;
        #define ZONE_PADDING(name)      struct zone_padding name;
        #else
        #define ZONE_PADDING(name)
        #endif
      
      B0rken:
      
        struct zone_padding {
                char                       x[];                 /*     0     0 */
      
                /* size: 0, cachelines: 0, members: 1 */
        } __attribute__((__aligned__(64)));
      
      Fixed:
      
        struct zone_padding {
                char                       x[0];                 /*     0     0 */
      
                /* size: 0, cachelines: 0, members: 1 */
        } __attribute__((__aligned__(64)));
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      2bcb01fc
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Deal with zero sized arrays in the midle of a union · 0987266c
      Arnaldo Carvalho de Melo authored
      gcc dislikes invalid C:
      
        /home/acme/git/build/v5.1-rc4+/fs/ceph/export.o
        /tmp/fullcircle.CvAfpM.c:591:22: error: flexible array member in union
           __u32              raw[];                /*     0     0 */
                              ^~~
      Before:
      
        $ pahole -C fid /home/acme/git/build/v5.1-rc4+/fs/ceph/export.o
        struct fid {
        	union {
        		struct {
        			u32        ino;                  /*     0     4 */
        			u32        gen;                  /*     4     4 */
        			u32        parent_ino;           /*     8     4 */
        			u32        parent_gen;           /*    12     4 */
        		} i32;                                   /*     0    16 */
        		struct {
        			u32        block;                /*     0     4 */
        			u16        partref;              /*     4     2 */
        			u16        parent_partref;       /*     6     2 */
        			u32        generation;           /*     8     4 */
        			u32        parent_block;         /*    12     4 */
        			u32        parent_generation;    /*    16     4 */
        		} udf;                                   /*     0    20 */
        		__u32              raw[];                /*     0     0 */
        	};                                               /*     0    20 */
      
        	/* size: 20, cachelines: 1, members: 1 */
        	/* last cacheline: 20 bytes */
        };
        $
      
      After:
      
        $ pahole -C fid /home/acme/git/build/v5.1-rc4+/fs/ceph/export.o
        struct fid {
        	union {
        		struct {
        			u32        ino;                  /*     0     4 */
        			u32        gen;                  /*     4     4 */
        			u32        parent_ino;           /*     8     4 */
        			u32        parent_gen;           /*    12     4 */
        		} i32;                                   /*     0    16 */
        		struct {
        			u32        block;                /*     0     4 */
        			u16        partref;              /*     4     2 */
        			u16        parent_partref;       /*     6     2 */
        			u32        generation;           /*     8     4 */
        			u32        parent_block;         /*    12     4 */
        			u32        parent_generation;    /*    16     4 */
        		} udf;                                   /*     0    20 */
        		__u32              raw[0];               /*     0     0 */
        	};                                               /*     0    20 */
      
        	/* size: 20, cachelines: 1, members: 1 */
        	/* last cacheline: 20 bytes */
        };
        $
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      0987266c
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Deal with zero sized arrays in the middle of a struct · 1101337a
      Arnaldo Carvalho de Melo authored
      Consider:
      
        struct ipc64_perm {
                __kernel_key_t          key;
                __kernel_uid32_t        uid;
                __kernel_gid32_t        gid;
                __kernel_uid32_t        cuid;
                __kernel_gid32_t        cgid;
                __kernel_mode_t         mode;
                                        /* pad if mode_t is u16: */
                unsigned char           __pad1[4 - sizeof(__kernel_mode_t)];
                unsigned short          seq;
                unsigned short          __pad2;
                __kernel_ulong_t        __unused1;
                __kernel_ulong_t        __unused2;
        };
      
      That is a roundabout way of using __attribute__(__aligned__(4)), but
      should work nonetheless.
      
      We were not putting the [0] in that zero sized array which ended up
      making gcc complain with:
      
        $ gcc -g -c shm.c
        shm.c:199:29: error: flexible array member not at end of struct
          unsigned char              __pad1[];            /*    24     0 */
                                     ^~~~~~
        $
      
      Now this works, i.e. generates compilable source code out of the
      type tags, be it from BTF or from DWARF, i.e. this is all from the
      internal representation of such types, agnostic wrt the original type
      format.
      
      So, the full circle:
      
        $ pahole -C ipc64_perm /home/acme/git/build/v5.1-rc4+/ipc/shm.o
        struct ipc64_perm {
        	__kernel_key_t             key;                  /*     0     4 */
        	__kernel_uid32_t           uid;                  /*     4     4 */
        	__kernel_gid32_t           gid;                  /*     8     4 */
        	__kernel_uid32_t           cuid;                 /*    12     4 */
        	__kernel_gid32_t           cgid;                 /*    16     4 */
        	__kernel_mode_t            mode;                 /*    20     4 */
        	unsigned char              __pad1[0];            /*    24     0 */
        	short unsigned int         seq;                  /*    24     2 */
        	short unsigned int         __pad2;               /*    26     2 */
      
        	/* XXX 4 bytes hole, try to pack */
      
        	__kernel_ulong_t           __unused1;            /*    32     8 */
        	__kernel_ulong_t           __unused2;            /*    40     8 */
      
        	/* size: 48, cachelines: 1, members: 11 */
        	/* sum members: 44, holes: 1, sum holes: 4 */
        	/* last cacheline: 48 bytes */
        };
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/ipc/shm.o > shm.c
        $ gcc -g -c shm.c
        $ pahole -C ipc64_perm shm.o
        struct ipc64_perm {
        	__kernel_key_t             key;                  /*     0     4 */
        	__kernel_uid32_t           uid;                  /*     4     4 */
        	__kernel_gid32_t           gid;                  /*     8     4 */
        	__kernel_uid32_t           cuid;                 /*    12     4 */
        	__kernel_gid32_t           cgid;                 /*    16     4 */
        	__kernel_mode_t            mode;                 /*    20     4 */
        	unsigned char              __pad1[0];            /*    24     0 */
        	short unsigned int         seq;                  /*    24     2 */
        	short unsigned int         __pad2;               /*    26     2 */
      
        	/* XXX 4 bytes hole, try to pack */
      
        	__kernel_ulong_t           __unused1;            /*    32     8 */
        	__kernel_ulong_t           __unused2;            /*    40     8 */
      
        	/* size: 48, cachelines: 1, members: 11 */
        	/* sum members: 44, holes: 1, sum holes: 4 */
        	/* last cacheline: 48 bytes */
        };
        $
      
      And for a chuckle, the original source code with a bit of history about
      struct layout worries:
      
      include/uapi/asm-generic/ipcbuf.h:
      
        /*
         * The generic ipc64_perm structure:
         * Note extra padding because this structure is passed back and forth
         * between kernel and user space.
         *
         * ipc64_perm was originally meant to be architecture specific, but
         * everyone just ended up making identical copies without specific
         * optimizations, so we may just as well all use the same one.
         *
         * Pad space is left for:
         * - 32-bit mode_t on architectures that only had 16 bit
         * - 32-bit seq
         * - 2 miscellaneous 32-bit values
         */
      
        struct ipc64_perm {
                __kernel_key_t          key;
                __kernel_uid32_t        uid;
                __kernel_gid32_t        gid;
                __kernel_uid32_t        cuid;
                __kernel_gid32_t        cgid;
                __kernel_mode_t         mode;
                                        /* pad if mode_t is u16: */
                unsigned char           __pad1[4 - sizeof(__kernel_mode_t)];
                unsigned short          seq;
                unsigned short          __pad2;
                __kernel_ulong_t        __unused1;
                __kernel_ulong_t        __unused2;
        };
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      1101337a
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Don't reuse 'type' in multiple scopes in the same function · 13aa13eb
      Arnaldo Carvalho de Melo authored
      Its confusing, so rename some variables.
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      13aa13eb
    • Arnaldo Carvalho de Melo's avatar
      core: Use unnatural alignment of struct embedded in another to infer __packed__ · c8fc6f5a
      Arnaldo Carvalho de Melo authored
      Since we don't have something like DW_AT_alignment for
      __attribute__((__packed__)), we need to use whatever hints that are
      there in the alignments to figure out if a naturally packed struct has
      the __attribute__((packed)) in the original sources, because that is
      needed to waiver its natural alignment requisites.
      
      For instance,
      
        /* Used at: btrfs.c */
        /* <1e7b> /home/acme/git/pahole/btrfs.c:199 */
        struct btrfs_block_group_cache {
                struct btrfs_key   key;                          /*     0    17 */
                struct btrfs_block_group_item item;              /*    17    24 */
      
                /* XXX 7 bytes hole, try to pack */
      
                struct btrfs_fs_info *     fs_info;              /*    48     8 */
                struct inode *             inode;                /*    56     8 */
      
      In the original source code, btrfs_block_group_item is marked
      __packed__, and being so, even seemingly unnecessarily, makes it, when
      embedded in another struct, like the above, forfeit its natural
      alingment, that would be 8 bytes, and instead appear right at the 17th
      byte offset...
      
        struct btrfs_block_group_item {
                __le64                     used;                 /*     0     8 */
                __le64                     chunk_objectid;       /*     8     8 */
                __le64                     flags;                /*    16     8 */
      
                /* size: 24, cachelines: 1, members: 3 */
                /* last cacheline: 24 bytes */
        } __attribute__((__packed__));
      
      So we need to, seeing its use at a unnatural offset, go backwards to the
      btrfs_block_group_item pahole internal data structure, 'struct type' and
      mark is_packed field as 'true', despite it not looking like a packed
      struct.
      
      Same thing with:
      
        struct ieee80211_mcs_info {
                u8                         rx_mask[10];          /*     0    10 */
                __le16                     rx_highest;           /*    10     2 */
                u8                         tx_params;            /*    12     1 */
                u8                         reserved[3];          /*    13     3 */
      
                /* size: 16, cachelines: 1, members: 4 */
                /* last cacheline: 16 bytes */
        };
      
      That is naturally aligned and as 16 bytes, a power of two, then when it appears at the end of:
      
        $ pahole -IC ieee80211_sta_ht_cap vht.o
        /* Used at: vht.c */
        /* <31ea> /home/acme/git/pahole/vht.c:1769 */
        struct ieee80211_sta_ht_cap {
        	u16                        cap;                  /*     0     2 */
        	bool                       ht_supported;         /*     2     1 */
        	u8                         ampdu_factor;         /*     3     1 */
        	u8                         ampdu_density;        /*     4     1 */
      
        	/* XXX 1 byte hole, try to pack */
      
        	struct ieee80211_mcs_info mcs;                   /*     6    16 */
      
        	/* size: 22, cachelines: 1, members: 5 */
        	/* sum members: 21, holes: 1, sum holes: 1 */
        	/* last cacheline: 22 bytes */
        };
        $
      
      We get that one byte hole if ieee80211_mcs_info isn't marked __packed__, as soon as we mark it:
      
        $ pahole -IC ieee80211_sta_ht_cap vht.o
        /* Used at: vht.c */
        /* <31ea> /home/acme/git/pahole/vht.c:1769 */
        struct ieee80211_sta_ht_cap {
        	u16                        cap;                  /*     0     2 */
        	bool                       ht_supported;         /*     2     1 */
        	u8                         ampdu_factor;         /*     3     1 */
        	u8                         ampdu_density;        /*     4     1 */
        	struct ieee80211_mcs_info mcs;                   /*     5    16 */
      
        	/* size: 22, cachelines: 1, members: 5 */
        	/* padding: 1 */
        	/* last cacheline: 22 bytes */
        };
        [acme@quaco pahole]$
      
      It works, so __packed__ in this case just says: trow away the natural
      alignment, make it 1 in whatever container structs.
      
      So, before emitting the types for some struct, we go back looking at
      each of its members and checking for such unnatural offsets, marking the
      types as __packed__. Now:
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/net/mac80211/vht.o | grep "^struct ieee80211_mcs_info" -A8
        struct ieee80211_mcs_info {
        	u8                         rx_mask[10];          /*     0    10 */
        	__le16                     rx_highest;           /*    10     2 */
        	u8                         tx_params;            /*    12     1 */
        	u8                         reserved[3];          /*    13     3 */
      
        	/* size: 16, cachelines: 1, members: 4 */
        	/* last cacheline: 16 bytes */
        } __attribute__((__packed__));
        $
      
        $ pfunct --compile /home/acme/git/build/v5.1-rc4+/fs/btrfs/free-space-tree.o | grep "^struct btrfs_block_group_item" -A7
        struct btrfs_block_group_item {
        	__le64                     used;                 /*     0     8 */
        	__le64                     chunk_objectid;       /*     8     8 */
        	__le64                     flags;                /*    16     8 */
      
        	/* size: 24, cachelines: 1, members: 3 */
        	/* last cacheline: 24 bytes */
        } __attribute__((__packed__));
        $
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      c8fc6f5a
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Fixup multi-dimensional zero sized arrays const handling · 6f0f9a88
      Arnaldo Carvalho de Melo authored
      Before:
      
        $ pahole -C piix_map_db /home/acme/git/build/v5.1-rc4+/drivers/ata/ata_piix.o
        struct piix_map_db {
        	const u32                  mask;                 /*     0     4 */
        	const u16                  port_enable;          /*     4     2 */
      
        	/* XXX 2 bytes hole, try to pack */
      
        	const const int            map[][4];             /*     8     0 */
      
        	/* size: 8, cachelines: 1, members: 3 */
        	/* sum members: 6, holes: 1, sum holes: 2 */
        	/* last cacheline: 8 bytes */
        };
        $
      
      After:
      
        $ pahole -C piix_map_db /home/acme/git/build/v5.1-rc4+/drivers/ata/ata_piix.o
        struct piix_map_db {
        	const u32                  mask;                 /*     0     4 */
        	const u16                  port_enable;          /*     4     2 */
      
        	/* XXX 2 bytes hole, try to pack */
      
        	const int                  map[][4];             /*     8     0 */
      
        	/* size: 8, cachelines: 1, members: 3 */
        	/* sum members: 6, holes: 1, sum holes: 2 */
        	/* last cacheline: 8 bytes */
        };
        $
      
      The DWARF tag sequence:
      
       <2><17e50>: Abbrev Number: 12 (DW_TAG_member)
          <17e51>   DW_AT_name        : map
          <17e55>   DW_AT_decl_file   : 1
          <17e56>   DW_AT_decl_line   : 160
          <17e57>   DW_AT_decl_column : 12
          <17e58>   DW_AT_type        : <0x17e78>
          <17e5c>   DW_AT_data_member_location: 8
      
       <1><17e78>: Abbrev Number: 15 (DW_TAG_const_type)
          <17e79>   DW_AT_type        : <0x17e63>
      
       <1><17e63>: Abbrev Number: 11 (DW_TAG_array_type)
          <17e64>   DW_AT_type        : <0xd8>
      
       <1><d8>: Abbrev Number: 15 (DW_TAG_const_type)
          <d9>   DW_AT_type        : <0xd1>
      
       <1><d1>: Abbrev Number: 120 (DW_TAG_base_type)
          <d2>   DW_AT_byte_size   : 4
          <d3>   DW_AT_encoding    : 5        (signed)
          <d4>   DW_AT_name        : int
      
        const -> array -> const -> int
      
      So just make the check be at least one dimension, if the number of
      elements is zero, then drop the double const.
      
      With this btfdiff for the allyesconfig ppc64 reference kernel we're
      using is again clean.
      
        $ pahole -F btf --sizes examples/vmlinux-aarch64 | wc -l
        51023
        $
      
      > 50K types with output from BTF and DWARF matching.
      
      Fixes: ccd67bdb ("fprintf: Print "const" for class members more early, in type__fprintf()")
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      6f0f9a88
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Allow suppressing the inferred __attribute__((__packed__)) · 9a4d7193
      Arnaldo Carvalho de Melo authored
      We use things like DW_AT_alignment, so not all of those attributes are
      inferred by formats like BTF that lack that info, allow suppressing the
      output and make btfdiff ask for both DWARF and BTF output to have this
      suppressed.
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      9a4d7193
    • Arnaldo Carvalho de Melo's avatar
      fprintf: Allow suppressing the output of force paddings at the end of structs · ec935ee4
      Arnaldo Carvalho de Melo authored
      Things like 'struct timex' in the linux kernel led to this output:
      Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
      ec935ee4