[PATCH 4/5] fprintf: Add a comment if a member type has an embedded flexible array

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>

For instance:

  acme@x1:~/git/pahole$ pahole cgroup_root
  struct cgroup_root {
          struct kernfs_root *       kf_root;              /*     0     8 */
          unsigned int               subsys_mask;          /*     8     4 */
          int                        hierarchy_id;         /*    12     4 */
          struct list_head           root_list;            /*    16    16 */
          struct callback_head       rcu;                  /*    32    16 */

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

          /* --- cacheline 1 boundary (64 bytes) --- */
          struct cgroup              cgrp __attribute__((__aligned__(64))); /*    64  1984 */

          /* XXX last struct has a flexible array, 3 holes */

          /* --- cacheline 32 boundary (2048 bytes) --- */
          struct cgroup *            cgrp_ancestor_storage; /*  2048     8 */
          atomic_t                   nr_cgrps;             /*  2056     4 */
          unsigned int               flags;                /*  2060     4 */
          char                       release_agent_path[4096]; /*  2064  4096 */
          /* --- cacheline 96 boundary (6144 bytes) was 16 bytes ago --- */
          char                       name[64];             /*  6160    64 */

          /* size: 6272, cachelines: 98, members: 11 */
          /* sum members: 6208, holes: 1, sum holes: 16 */
          /* padding: 48 */
          /* member types with holes: 1, total: 3 */
          /* forced alignments: 1, forced holes: 1, sum forced holes: 16 */
  } __attribute__((__aligned__(64)));
  acme@x1:~/git/pahole$

And then:

  acme@x1:~/git/pahole$ pahole cgroup | tail -20
  	/* XXX last struct has 1 hole */

  	/* --- cacheline 30 boundary (1920 bytes) was 32 bytes ago --- */
  	atomic_t                   congestion_count;     /*  1952     4 */
  	struct cgroup_freezer_state freezer;             /*  1956    16 */

  	/* XXX last struct has 1 hole */
  	/* XXX 4 bytes hole, try to pack */

  	struct bpf_local_storage * bpf_cgrp_storage;     /*  1976     8 */
  	/* --- cacheline 31 boundary (1984 bytes) --- */
  	struct cgroup *            ancestors[];          /*  1984     0 */

  	/* size: 1984, cachelines: 31, members: 42 */
  	/* sum members: 1952, holes: 3, sum holes: 32 */
  	/* member types with holes: 3, total: 3 */
  	/* paddings: 1, sum paddings: 4 */
  	/* forced alignments: 1 */
  };

  acme@x1:~/git/pahole$

Care must be taken on how to use that cgroup->ancestors field since
cgroup_root->cgrp is in the middle of 'struct cgroup_root', so accesses
to cgroup->ancestors[1] would be accessing other fields of cgroup_root
after cgrp, i.e. further analysis and checks in the code handling those
structs is needed.

This comes from discussions with Willy Tarreau after Gustavo A. R.
Silva's presentation at Kernel Recipes'2024:

  https://speakerdeck.com/ennael/enhancing-spatial-safety-fixing-thousands-of-wflex-array-member-not-at-end-warnings?slide=11

Cc: "Gustavo A. R. Silva" <gustavoars@xxxxxxxxxx>
Cc: Willy Tarreau <w@xxxxxx>
Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx>
---
 dwarves_fprintf.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/dwarves_fprintf.c b/dwarves_fprintf.c
index ffbe6fbd3f5c405a..94a152183b0725cf 100644
--- a/dwarves_fprintf.c
+++ b/dwarves_fprintf.c
@@ -1513,7 +1513,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, bit_padding;
-	bool first = true;
+	bool first = true, has_embedded_flexible_array;
 	/*
 	 * We may not yet have looked for holes and paddings in this member's
 	 * struct type.
@@ -1525,8 +1525,9 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
 	bit_padding = class->bit_padding;
 	nr_holes = class->nr_holes;
 	nr_bit_holes = class->nr_bit_holes;
+	has_embedded_flexible_array = class__has_embedded_flexible_array(class, cu);
 
-	if (!padding && !bit_padding && !nr_holes && !nr_bit_holes)
+	if (!padding && !bit_padding && !nr_holes && !nr_bit_holes && !has_embedded_flexible_array)
 		return 0;
 
 	if (!(*newline)++) {
@@ -1536,11 +1537,16 @@ static size_t class__fprintf_member_type_holes(struct class *class, const struct
 
 	printed += fprintf(fp, "\n%.*s/* XXX last struct has", conf->indent, tabs);
 
+	if (has_embedded_flexible_array) {
+		printed += fprintf(fp, " a flexible array");
+		first = false;
+	}
+
 	if (padding) {
 		++holes->nr_paddings;
 		holes->sum_paddings += padding;
 
-		printed += fprintf(fp, " %d byte%s of padding", padding, padding != 1 ? "s" : "");
+		printed += fprintf(fp, "%s %d byte%s of padding", first ? "" : ",", padding, padding != 1 ? "s" : "");
 		first = false;
 	}
 
-- 
2.46.2





[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux