diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2024-02-09 16:13:27 -0300 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2024-02-09 17:46:15 -0300 |
commit | 4fa81a30b9ca3b78212fb93443f5508a0af29043 (patch) | |
tree | ffaf0a298f4242e3a7e1d3cbb83335f98883128a | |
parent | 85bdd96404efca198ff441ab73513a6b3bb3a4e0 (diff) | |
download | pahole-4fa81a30b9ca3b78212fb93443f5508a0af29043.tar.gz |
fprintf: Print number of bit holes in class member types
In addition to paddings (holes at the end of a struct) and byte holes,
inform about bit holes in bitfields in the middle of the structs of
non-pointer members.
For instance, for 'struct task_struct' in the Linux kernel we get this
extra info:
--- task_struct.before.c 2024-02-09 16:19:34.221134835 -0300
+++ task_struct.after.c 2024-02-09 17:45:41.137097839 -0300
@@ -35,6 +35,9 @@
/* --- 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 */
@@ -405,12 +408,12 @@
/* --- cacheline 145 boundary (9280 bytes) --- */
struct thread_struct thread __attribute__((__aligned__(64))); /* 9280 4416 */
- /* XXX last struct has 1 hole */
+ /* 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 of those holes: 6 */
+ /* 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 */
};
Out of curiosity, lets try one taking advantage that most if not all
distros these days comes with /sys/kernel/btf/vmlinux so that we can ask
just for the type, without specifying where to find it:
$ pahole sched_dl_entity
struct sched_dl_entity {
struct rb_node rb_node; /* 0 24 */
u64 dl_runtime; /* 24 8 */
u64 dl_deadline; /* 32 8 */
u64 dl_period; /* 40 8 */
u64 dl_bw; /* 48 8 */
u64 dl_density; /* 56 8 */
/* --- cacheline 1 boundary (64 bytes) --- */
s64 runtime; /* 64 8 */
u64 deadline; /* 72 8 */
unsigned int flags; /* 80 4 */
unsigned int dl_throttled:1; /* 84: 0 4 */
unsigned int dl_yielded:1; /* 84: 1 4 */
unsigned int dl_non_contending:1; /* 84: 2 4 */
unsigned int dl_overrun:1; /* 84: 3 4 */
/* XXX 28 bits hole, try to pack */
struct hrtimer dl_timer; /* 88 64 */
/* XXX last struct has 4 bytes of padding */
/* --- cacheline 2 boundary (128 bytes) was 24 bytes ago --- */
struct hrtimer inactive_timer; /* 152 64 */
/* XXX last struct has 4 bytes of padding */
/* --- cacheline 3 boundary (192 bytes) was 24 bytes ago --- */
struct sched_dl_entity * pi_se; /* 216 8 */
/* size: 224, cachelines: 4, members: 16 */
/* sum members: 220 */
/* sum bitfield members: 4 bits, bit holes: 1, sum bit holes: 28 bits */
/* paddings: 2, sum paddings: 8 */
/* last cacheline: 32 bytes */
};
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r-- | dwarves_fprintf.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c index 1169d359..2fa489a4 100644 --- a/dwarves_fprintf.c +++ b/dwarves_fprintf.c @@ -1465,7 +1465,9 @@ out: struct member_types_holes { uint16_t nr_paddings; uint16_t nr_with_holes; + uint16_t nr_with_bit_holes; uint16_t total_nr_holes; + uint16_t total_nr_bit_holes; uint32_t sum_paddings; }; @@ -1475,7 +1477,7 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct { size_t printed = 0; uint16_t padding; - uint8_t nr_holes; + uint8_t nr_holes, nr_bit_holes; bool first = true; /* * We may not yet have looked for holes and paddings in this member's @@ -1486,8 +1488,9 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct padding = class->padding; nr_holes = class->nr_holes; + nr_bit_holes = class->nr_bit_holes; - if (!padding && !nr_holes) + if (!padding && !nr_holes && !nr_bit_holes) return 0; if (!(*newline)++) { @@ -1510,6 +1513,14 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct holes->total_nr_holes += nr_holes; printed += fprintf(fp, "%s %d hole%s", first ? "" : ",", nr_holes, nr_holes != 1 ? "s" : ""); + first = false; + } + + if (nr_bit_holes) { + ++holes->nr_with_bit_holes; + holes->total_nr_bit_holes += nr_bit_holes; + + printed += fprintf(fp, "%s %d bit hole%s", first ? "" : ",", nr_bit_holes, nr_bit_holes != 1 ? "s" : ""); } return printed + fprintf(fp, " */"); @@ -1873,10 +1884,21 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu, printed += fprintf(fp, "%.*s/* padding: %u */\n", cconf.indent, tabs, class->padding); - if (member_types_holes.nr_with_holes > 0) { - printed += fprintf(fp, "%.*s/* member types with holes: %u, total of those holes: %u */\n", - cconf.indent, tabs, - member_types_holes.nr_with_holes, member_types_holes.total_nr_holes); + + if (member_types_holes.nr_with_holes > 0 || member_types_holes.nr_with_bit_holes > 0) { + bool first = true; + + printed += fprintf(fp, "%.*s/* member types with ", cconf.indent, tabs); + if (member_types_holes.nr_with_holes > 0) { + printed += fprintf(fp, "holes: %u, total: %u", + member_types_holes.nr_with_holes, member_types_holes.total_nr_holes); + first = false; + } + if (member_types_holes.nr_with_bit_holes > 0) { + printed += fprintf(fp, "%sbit holes: %u, total: %u", first ? "" : ", ", + member_types_holes.nr_with_bit_holes, member_types_holes.total_nr_bit_holes); + } + printed += fprintf(fp, " */\n"); } if (member_types_holes.nr_paddings > 0) printed += fprintf(fp, "%.*s/* paddings: %u, sum paddings: " |