pahole:

- When expanding types using 'pahole -E' do it for union and struct typedefs and for enums too.

  E.g: that 'state' field in 'struct module':

    $ pahole module | head
    struct module {
            enum module_state          state;                /*     0     4 */

            /* XXX 4 bytes hole, try to pack */

            struct list_head           list;                 /*     8    16 */
            char                       name[56];             /*    24    56 */
            /* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */
            struct module_kobject      mkobj;                /*    80    96 */
            /* --- cacheline 2 boundary (128 bytes) was 48 bytes ago --- */
    $

  now gets expanded:

    $ pahole -E module | head
    struct module {
            enum module_state {
                    MODULE_STATE_LIVE     = 0,
                    MODULE_STATE_COMING   = 1,
                    MODULE_STATE_GOING    = 2,
                    MODULE_STATE_UNFORMED = 3,
            } state; /*     0     4 */

            /* XXX 4 bytes hole, try to pack */

    $

- Print number of holes, bit holes and bit paddings in class member types.

  Doing this recursively to show how much waste a complex data structure has
  is something that still needs to be done, there were the low hanging fruits
  on the path to having that feature.

  For instance, for 'struct task_struct' in the Linux kernel we get this
  extra info:

    --- task_struct.before.c      2024-02-09 11:38:39.249638750 -0300
    +++ task_struct.after.c       2024-02-09 16:19:34.221134835 -0300
    @@ -29,6 +29,12 @@

          /* --- cacheline 2 boundary (128 bytes) --- */
          struct sched_entity        se;                   /*   128   256 */
    +
    +     /* XXX last struct has 3 holes */
    +
          /* --- cacheline 6 boundary (384 bytes) --- */
          struct sched_rt_entity     rt;                   /*   384    48 */
          struct sched_dl_entity     dl;                   /*   432   224 */
    +
    +       /* XXX last struct has 1 bit hole */
    +
          /* --- cacheline 10 boundary (640 bytes) was 16 bytes ago --- */
          const struct sched_class  * sched_class;         /*   656     8 */
          struct rb_node             core_node;            /*   664    24 */
    @@ -100,6 +103,9 @@
          /* --- cacheline 35 boundary (2240 bytes) was 16 bytes ago --- */
          struct list_head           tasks;                /*  2256    16 */
          struct plist_node          pushable_tasks;       /*  2272    40 */
    +
    +     /* XXX last struct has 1 hole */
    +
          /* --- cacheline 36 boundary (2304 bytes) was 8 bytes ago --- */
          struct rb_node             pushable_dl_tasks;    /*  2312    24 */
          struct mm_struct *         mm;                   /*  2336     8 */
    @@ -172,6 +178,9 @@
          /* XXX last struct has 4 bytes of padding */

          struct vtime               vtime;                /*  2744    48 */
    +
    +     /* XXX last struct has 1 hole */
    +
          /* --- cacheline 43 boundary (2752 bytes) was 40 bytes ago --- */
          atomic_t                   tick_dep_mask;        /*  2792     4 */

    @@ -396,9 +405,12 @@
          /* --- cacheline 145 boundary (9280 bytes) --- */
          struct thread_struct       thread __attribute__((__aligned__(64))); /*  9280  4416 */

    +       /* XXX last struct has 1 hole, 1 bit hole */
    +
          /* size: 13696, cachelines: 214, members: 262 */
          /* sum members: 13518, holes: 21, sum holes: 162 */
          /* sum bitfield members: 82 bits, bit holes: 2, sum bit holes: 46 bits */
          /* member types with holes: 4, total: 6, bit holes: 2, total: 2 */
          /* paddings: 6, sum paddings: 49 */
          /* forced alignments: 2, forced holes: 2, sum forced holes: 88 */
     };

- Introduce --contains_enumerator=ENUMERATOR_NAME:

  E.g.:

      $ pahole --contains_enumerator S_VERSION
      enum file_time_flags {
             S_ATIME   = 1,
             S_MTIME   = 2,
             S_CTIME   = 4,
             S_VERSION = 8,
      }
      $

  The shorter form --contains_enum is also accepted.

- Fix pretty printing when using DWARF, where sometimes the class (-C) and a specified "type_enum",
  may not be present on the same CU, so wait till both are found.

  Now this example that reads the 'struct perf_event_header' and 'enum perf_event_type'
  from the DWARF info in ~/bin/perf to pretty print records in the perf.data file works
  just like when using type info from BTF in ~/bin/perf:

      $ pahole -F dwarf -V ~/bin/perf \
                --header=perf_file_header \
                --seek_bytes '$header.data.offset' \
                --size_bytes='$header.data.size' \
                -C 'perf_event_header(sizeof,type,type_enum=perf_event_type,filter=type==PERF_RECORD_MMAP2)' \
                --prettify perf.data --count 1
      pahole: sizeof_operator for 'perf_event_header' is 'size'
      pahole: type member for 'perf_event_header' is 'type'
      pahole: type enum for 'perf_event_header' is 'perf_event_type'
      pahole: filter for 'perf_event_header' is 'type==PERF_RECORD_MMAP2'
      pahole: seek bytes evaluated from --seek_bytes=$header.data.offset is 0x3f0
      pahole: size bytes evaluated from --size_bytes=$header.data.size is 0xd10
      // type=perf_event_header, offset=0xc20, sizeof=8, real_sizeof=112
      {
            .header = {
                    .type = PERF_RECORD_MMAP2,
                    .misc = 2,
                    .size = 112,
            },
            .pid = 1533617,
            .tid = 1533617,
            .start = 94667542700032,
            .len = 90112,
            .pgoff = 16384,{
                    .maj = 0,
                    .min = 33,
                    .ino = 35914923,
                    .ino_generation = 26870,
            },{
                    .build_id_size = 0,
                    .__reserved_1 = 0,
                    .__reserved_2 = 0,
                    .build_id = { 33, 0, 0, 0, -85, 4, 36, 2, 0, 0, 0, 0, -10, 104, 0, 0, 0, 0, 0, 0 },
            },
            .prot = 5,
            .flags = 2,
            .filename = "/usr/bin/ls",
      },
      $

DWARF loader:

- Add support for DW_TAG_constant, first seen in Go DWARF.

- Fix loading DW_TAG_subroutine_type generated by the Go compiler, where it may
  have a DW_AT_byte_size. Go DWARF. And pretty print it as if
  it was from C, this helped in writing BPF programs to attach to Go binaries, using
  uprobes.

BTF loader:

- Fix loading of 32-bit signed enums.

BTF encoder:

- Add 'pahole --btf_features' to allow consumers to specify an opt-in set of
  features they want to use in BTF encoding.

  Supported features are a comma-separated combination of

          encode_force    Ignore invalid symbols when encoding BTF.
          var             Encode variables using BTF_KIND_VAR in BTF.
          float           Encode floating-point types in BTF.
          decl_tag        Encode declaration tags using BTF_KIND_DECL_TAG.
          type_tag        Encode type tags using BTF_KIND_TYPE_TAG.
          enum64          Encode enum64 values with BTF_KIND_ENUM64.
          optimized_func  Encode representations of optimized functions
                          with suffixes like ".isra.0" etc
          consistent_func Avoid encoding inconsistent static functions.
                          These occur when a parameter is optimized out
                          in some CUs and not others, or when the same
                          function name has inconsistent BTF descriptions
                          in different CUs.

  Specifying "--btf_features=all" is the equivalent to setting all of the
  above.  If pahole does not know about a feature specified in
  --btf_features it silently ignores it.

  The --btf_features can either be specified via a single comma-separated
  list
          --btf_features=enum64,float

  ...or via multiple --btf_features values

          --btf_features=enum64 --btf_features=float

  These properties allow us to use the --btf_features option in the kernel
  scripts/pahole_flags.sh script to specify the desired set of BTF
  features.

  If a feature named in --btf_features is not present in the version of
  pahole used, BTF encoding will not complain.  This is desired because it
  means we no longer have to tie new features to a specific pahole
  version.

  Use --btf_features_strict to change that behaviour and bail out if one of
  the requested features isn't present.

  To see the supported features, use:

    $ pahole --supported_btf_features
    encode_force,var,float,decl_tag,type_tag,enum64,optimized_func,consistent_func
    $

btfdiff:

- Parallelize loading BTF and DWARF, speeding up a bit.

- Do type expansion to cover "private" types and enumerations.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
