aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2024-02-09 16:13:27 -0300
committerArnaldo Carvalho de Melo <acme@redhat.com>2024-02-10 16:51:30 -0300
commit1fd08c0f0021e7fbaa31b1add7667b147edd5a9c (patch)
treebfc46322bde77f1b9f2a6961f34160cbd2622772
parent4fa81a30b9ca3b78212fb93443f5508a0af29043 (diff)
downloadpahole-1fd08c0f0021e7fbaa31b1add7667b147edd5a9c.tar.gz
fprintf: Print number of bit paddings in class member types
In addition to paddings (holes at the end of a struct), byte holes and bit holes, inform about bit paddings in bitfields at the end of the structs of non-pointer members. For instance, see 'struct device' in the Linux kernel, mostly without holes (just padding, 3 bytes and 3 bits) but with members with types that have holes: $ pahole device struct device { struct kobject kobj; /* 0 64 */ /* XXX last struct has 27 bits of padding */ /* --- cacheline 1 boundary (64 bytes) --- */ struct device * parent; /* 64 8 */ struct device_private * p; /* 72 8 */ const char * init_name; /* 80 8 */ const struct device_type * type; /* 88 8 */ const struct bus_type * bus; /* 96 8 */ struct device_driver * driver; /* 104 8 */ void * platform_data; /* 112 8 */ void * driver_data; /* 120 8 */ /* --- cacheline 2 boundary (128 bytes) --- */ struct mutex mutex; /* 128 32 */ struct dev_links_info links; /* 160 56 */ /* XXX last struct has 4 bytes of padding */ /* --- cacheline 3 boundary (192 bytes) was 24 bytes ago --- */ struct dev_pm_info power; /* 216 312 */ /* XXX last struct has 2 holes, 3 bit holes */ /* --- cacheline 8 boundary (512 bytes) was 16 bytes ago --- */ struct dev_pm_domain * pm_domain; /* 528 8 */ struct em_perf_domain * em_pd; /* 536 8 */ struct dev_pin_info * pins; /* 544 8 */ struct dev_msi_info msi; /* 552 16 */ const struct dma_map_ops * dma_ops; /* 568 8 */ /* --- cacheline 9 boundary (576 bytes) --- */ u64 * dma_mask; /* 576 8 */ u64 coherent_dma_mask; /* 584 8 */ u64 bus_dma_limit; /* 592 8 */ const struct bus_dma_region * dma_range_map; /* 600 8 */ struct device_dma_parameters * dma_parms; /* 608 8 */ struct list_head dma_pools; /* 616 16 */ struct cma * cma_area; /* 632 8 */ /* --- cacheline 10 boundary (640 bytes) --- */ struct io_tlb_mem * dma_io_tlb_mem; /* 640 8 */ struct dev_archdata archdata; /* 648 0 */ struct device_node * of_node; /* 648 8 */ struct fwnode_handle * fwnode; /* 656 8 */ int numa_node; /* 664 4 */ dev_t devt; /* 668 4 */ u32 id; /* 672 4 */ spinlock_t devres_lock; /* 676 4 */ struct list_head devres_head; /* 680 16 */ const struct class * class; /* 696 8 */ /* --- cacheline 11 boundary (704 bytes) --- */ const struct attribute_group * * groups; /* 704 8 */ void (*release)(struct device *); /* 712 8 */ struct iommu_group * iommu_group; /* 720 8 */ struct dev_iommu * iommu; /* 728 8 */ struct device_physical_location * physical_location; /* 736 8 */ enum device_removable removable; /* 744 4 */ bool offline_disabled:1; /* 748: 0 1 */ bool offline:1; /* 748: 1 1 */ bool of_node_reused:1; /* 748: 2 1 */ bool state_synced:1; /* 748: 3 1 */ bool can_match:1; /* 748: 4 1 */ /* size: 752, cachelines: 12, members: 45 */ /* padding: 3 */ /* member types with holes: 1, total: 2, bit holes: 1, total: 3, bit paddings: 1, total: 27 bits */ /* paddings: 1, sum paddings: 4 */ /* bit_padding: 3 bits */ /* last cacheline: 48 bytes */ }; $ Now look at the first member bit padding: $ pahole kobject struct kobject { const char * name; /* 0 8 */ struct list_head entry; /* 8 16 */ struct kobject * parent; /* 24 8 */ struct kset * kset; /* 32 8 */ const struct kobj_type * ktype; /* 40 8 */ struct kernfs_node * sd; /* 48 8 */ struct kref kref; /* 56 4 */ unsigned int state_initialized:1; /* 60: 0 4 */ unsigned int state_in_sysfs:1; /* 60: 1 4 */ unsigned int state_add_uevent_sent:1; /* 60: 2 4 */ unsigned int state_remove_uevent_sent:1; /* 60: 3 4 */ unsigned int uevent_suppress:1; /* 60: 4 4 */ /* size: 64, cachelines: 1, members: 12 */ /* bit_padding: 27 bits */ }; $ Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--dwarves_fprintf.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index 2fa489a4..9e5e6631 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -1464,11 +1464,13 @@ out:
struct member_types_holes {
uint16_t nr_paddings;
+ uint16_t nr_with_bit_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;
+ uint32_t sum_bit_paddings;
};
static size_t class__fprintf_member_type_holes(struct class *class, const struct cu *cu,
@@ -1477,7 +1479,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, nr_bit_holes;
+ uint8_t nr_holes, nr_bit_holes, bit_padding;
bool first = true;
/*
* We may not yet have looked for holes and paddings in this member's
@@ -1487,10 +1489,11 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
class__infer_packed_attributes(class, cu);
padding = class->padding;
+ bit_padding = class->bit_padding;
nr_holes = class->nr_holes;
nr_bit_holes = class->nr_bit_holes;
- if (!padding && !nr_holes && !nr_bit_holes)
+ if (!padding && !bit_padding && !nr_holes && !nr_bit_holes)
return 0;
if (!(*newline)++) {
@@ -1508,6 +1511,14 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
first = false;
}
+ if (bit_padding) {
+ ++holes->nr_with_bit_paddings;
+ holes->sum_bit_paddings += bit_padding;
+
+ printed += fprintf(fp, "%s %d bit%s of padding", first ? "" : ",", bit_padding, bit_padding != 1 ? "s" : "");
+ first = false;
+ }
+
if (nr_holes) {
++holes->nr_with_holes;
holes->total_nr_holes += nr_holes;
@@ -1885,7 +1896,9 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
cconf.indent,
tabs, class->padding);
- if (member_types_holes.nr_with_holes > 0 || member_types_holes.nr_with_bit_holes > 0) {
+ if (member_types_holes.nr_with_holes > 0 ||
+ member_types_holes.nr_with_bit_holes > 0 ||
+ member_types_holes.nr_with_bit_paddings > 0) {
bool first = true;
printed += fprintf(fp, "%.*s/* member types with ", cconf.indent, tabs);
@@ -1897,6 +1910,13 @@ static size_t __class__fprintf(struct class *class, const struct cu *cu,
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);
+ first = false;
+ }
+ if (member_types_holes.nr_with_bit_paddings > 0) {
+ printed += fprintf(fp, "%sbit paddings: %u, total: %u bit%s", first ? "" : ", ",
+ member_types_holes.nr_with_bit_paddings,
+ member_types_holes.sum_bit_paddings,
+ member_types_holes.sum_bit_paddings > 1 ? "s" : "");
}
printed += fprintf(fp, " */\n");
}