fprintf: Fixup handling of unnamed bitfields

We were only handling holes inside bitfields as a request to change the
byte_offset, which is not the case when instead of 'int foo:0;' we have
'int foo:6;' to ask for a explicit 6 bit hole inside a bitfield, like
in:

Before this patch:

  $ pahole -F btf -C kvm_mmu_page_role /home/acme/git/build/v5.1-rc4+/arch/x86/kvm/hyperv.o
  union kvm_mmu_page_role {
          u32                        word;               /*     0     4 */
          struct {
                  unsigned int       level:4;            /*     0: 0  4 */
                  unsigned int       gpte_is_8_bytes:1;  /*     0: 4  4 */
                  unsigned int       quadrant:2;         /*     0: 5  4 */
                  unsigned int       direct:1;           /*     0: 7  4 */
                  unsigned int       access:3;           /*     0: 8  4 */
                  unsigned int       invalid:1;          /*     0:11  4 */
                  unsigned int       nxe:1;              /*     0:12  4 */
                  unsigned int       cr0_wp:1;           /*     0:13  4 */
                  unsigned int       smep_andnot_wp:1;   /*     0:14  4 */
                  unsigned int       smap_andnot_wp:1;   /*     0:15  4 */
                  unsigned int       ad_disabled:1;      /*     0:16  4 */
                  unsigned int       guest_mode:1;       /*     0:17  4 */

                  /* XXX 6 bits hole, try to pack */

                  /* Force alignment to the next boundary: */
                  unsigned int       :0;

                  unsigned int       smm:8;              /*     0:24  4 */
          };                                             /*     0     4 */
  };
  $

After:

  $ pahole -F btf -C kvm_mmu_page_role /home/acme/git/build/v5.1-rc4+/arch/x86/kvm/hyperv.o
  union kvm_mmu_page_role {
          u32                        word;               /*     0     4 */
          struct {
                  unsigned int       level:4;            /*     0: 0  4 */
                  unsigned int       gpte_is_8_bytes:1;  /*     0: 4  4 */
                  unsigned int       quadrant:2;         /*     0: 5  4 */
                  unsigned int       direct:1;           /*     0: 7  4 */
                  unsigned int       access:3;           /*     0: 8  4 */
                  unsigned int       invalid:1;          /*     0:11  4 */
                  unsigned int       nxe:1;              /*     0:12  4 */
                  unsigned int       cr0_wp:1;           /*     0:13  4 */
                  unsigned int       smep_andnot_wp:1;   /*     0:14  4 */
                  unsigned int       smap_andnot_wp:1;   /*     0:15  4 */
                  unsigned int       ad_disabled:1;      /*     0:16  4 */
                  unsigned int       guest_mode:1;       /*     0:17  4 */

                  /* XXX 6 bits hole, try to pack */
                  unsigned int       :6;

                  unsigned int       smm:8;              /*     0:24  4 */
          };                                             /*     0     4 */
  };

Cc: Alexei Starovoitov <ast@fb.com>
Cc: Andrii Nakryiko <andriin@fb.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Yonghong Song <yhs@fb.com>
Fixes: a104eb1ea1 ("fprintf: Notice explicit bitfield alignment modifications")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2019-04-10 18:11:55 -03:00
parent 3247a777dc
commit f909f13dd7
1 changed files with 12 additions and 2 deletions

View File

@ -1381,16 +1381,26 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
*/
last_size != 0) {
if (last->bit_hole != 0 && pos->bitfield_size) {
uint8_t bitfield_size = last->bit_hole;
type = cu__type(cu, pos->tag.type);
if (type == NULL) {
printed += fprintf(fp, "%.*s", cconf.indent, tabs);
printed += tag__id_not_found_fprintf(fp, pos->tag.type);
continue;
}
printed += fprintf(fp, "\n%.*s/* Force alignment to the next boundary: */\n", cconf.indent, tabs);
/*
* Now check if this isn't something like 'unsigned :N' with N > 0,
* i.e. _explicitely_ adding a bit hole.
*/
if (last->byte_offset != pos->byte_offset) {
printed += fprintf(fp, "\n%.*s/* Force alignment to the next boundary: */\n", cconf.indent, tabs);
bitfield_size = 0;
}
printed += fprintf(fp, "%.*s", cconf.indent, tabs);
printed += type__fprintf(type, cu, "", &cconf, fp);
printed += fprintf(fp, ":0;\n");
printed += fprintf(fp, ":%u;\n", bitfield_size);
}
if (pos->byte_offset < last->byte_offset ||