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-10 16:51:30 -0300 |
commit | 1fd08c0f0021e7fbaa31b1add7667b147edd5a9c (patch) | |
tree | bfc46322bde77f1b9f2a6961f34160cbd2622772 | |
parent | 4fa81a30b9ca3b78212fb93443f5508a0af29043 (diff) | |
download | pahole-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.c | 26 |
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"); } |