dwarves: Fix classification of byte/bit hole for aligned bitfield

This patch fixes a bug in class__find_holes() with determining byte hole
as a bit hole in case where previous member is not bitfield, but current
one is aligned bitfield. See example below, notice hole classification
hw_stopped field..

  $ cat test/bit_test.c
  struct s {
          long unused: 62;
          /* 2 bit hole */
          int hw_stopped;
          /* 4 byte hole */
          long unused2: 55;
          /* 9 bit padding */
  };

  int main() {
          static struct s s;
          return 0;
  }

  $ clang -g test/bit_test.c -o test/bit_test

  $ pahole -JV test/bit_test
  File test/bit_test:
  [1] STRUCT s kind_flag=1 size=24 vlen=3
          unused type_id=2 bitfield_size=62 bits_offset=0
          hw_stopped type_id=3 bitfield_size=0 bits_offset=64
          unused2 type_id=2 bitfield_size=55 bits_offset=128
  [2] INT long int size=8 bit_offset=0 nr_bits=64 encoding=SIGNED
  [3] INT int size=4 bit_offset=0 nr_bits=32 encoding=SIGNED

BEFORE:

  $ pahole -F btf test/bit_test
  struct s {
          long int                   unused:62;            /*     0: 0  8 */

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

          int                        hw_stopped;           /*     8     4 */

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

          long int                   unused2:55;           /*    16: 0  8 */

          /* size: 24, cachelines: 1, members: 3 */
          /* sum members: 4 */
          /* sum bitfield members: 117 bits, bit holes: 2, sum bit holes: 34 bits */
          /* bit_padding: 9 bits */
          /* last cacheline: 24 bytes */
  };

AFTER:

  $ pahole -F btf test/bit_test
  struct s {
          long int                   unused:62;            /*     0: 0  8 */

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

          int                        hw_stopped;           /*     8     4 */

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

          long int                   unused2:55;           /*    16: 0  8 */

          /* size: 24, cachelines: 1, members: 3 */
          /* sum members: 4, holes: 1, sum holes: 4 */
          /* sum bitfield members: 117 bits, bit holes: 1, sum bit holes: 2 bits */
          /* bit_padding: 9 bits */
          /* last cacheline: 24 bytes */
  };

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Yonghong Song <yhs@fb.com>
Cc: dwarves@vger.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Andrii Nakryiko 2019-04-03 00:01:46 -07:00 committed by Arnaldo Carvalho de Melo
parent 78c110a7ea
commit 5d1c4029bd
1 changed files with 2 additions and 2 deletions

View File

@ -1223,9 +1223,9 @@ void class__find_holes(struct class *class)
if (pos->bitfield_size) {
int aligned_start = pos->byte_offset * 8;
/* we can have some alignment byte padding left,
* but we need to be carful about bitfield spanning
* but we need to be careful about bitfield spanning
* multiple aligned boundaries */
if (last_seen_bit < aligned_start && aligned_start < bit_start) {
if (last_seen_bit < aligned_start && aligned_start <= bit_start) {
byte_holes = pos->byte_offset - last_seen_bit / 8;
last_seen_bit = aligned_start;
}