All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jacob Keller <jacob.e.keller@intel.com>
To: linux-sparse@vger.kernel.org
Subject: sparse attribute packed on structures
Date: Tue, 15 Dec 2020 10:15:35 -0800	[thread overview]
Message-ID: <0e8d816a-0849-c761-e0dc-93c3e5674e62@intel.com> (raw)

Hi,

I'm looking into an issue with sparse not calculating the size of a
packed structure correctly, causing some static assertions to fail due
to an incorrect size.

With a structure like this:

struct a {
	uint32_t a;
	uint8_t b;
	uint8_t c;
} __attribute__ ((packed));

The packed attribute doesn't seem to get applied to the whole structure.
Thus, the sparse sizeof evaluation for this results in 8 bytes (64
bits), when GCC would produce a structure of size 6 bytes (48 bits).

If I use something instead like this:

struct a {
	uint32_t a __attribute__ ((packed));
	uint8_t b __attribute__ ((packed));
	uint8_t c __attribute__ ((packed));
} __attribute__ ((packed));

Then the size is calculated correctly.

I saw that there is support in parse.c for parsing attribute packed, but
it doesn't seem to have a way to propagate from a structure down to its
members.

I thought it would be relatively straight forward to implement by adding
a MOD_PACKED, but that doesn't seem to actually get assigned to the
struct symbol, so when I tried that it didn't work.

I would very much like to help get structure size packing to work properly.

The following diff is what I tried initially, but it doesn't actually
work as expected. I'm not sure what is wrong, or what is the best method
to actually get the packed modifier to save into the structure symbol so
that it can be checked when determining the structure size.

Help would be appreciated.

Thanks,
Jake

---

diff --git i/parse.c w/parse.c
index 0b2685707b82..96beae80c300 100644
--- i/parse.c
+++ w/parse.c
@@ -1086,13 +1086,6 @@ static struct token *ignore_attribute(struct
token *token, struct symbol *attr,
        return token;
 }

-static struct token *attribute_packed(struct token *token, struct
symbol *attr, struct decl_state *ctx)
-{
-       if (!ctx->ctype.alignment)
-               ctx->ctype.alignment = 1;
-       return token;
-}
-
 static struct token *attribute_aligned(struct token *token, struct
symbol *attr, struct decl_state *ctx)
 {
        int alignment = max_alignment;
@@ -1142,6 +1135,14 @@ static struct token *attribute_bitwise(struct
token *token, struct symbol *attr,
        return token;
 }

+static struct token *attribute_packed(struct token *token, struct
symbol *attr, struct decl_state *ctx)
+{
+       apply_mod(&token->pos, &ctx->ctype.modifiers, MOD_PACKED);
+       if (!ctx->ctype.alignment)
+               ctx->ctype.alignment = 1;
+       return token;
+}
+
 static struct ident *numerical_address_space(int asn)
 {
        char buff[32];
diff --git i/symbol.c w/symbol.c
index 1a083fb8432c..6e0d3ba74bd6 100644
--- i/symbol.c
+++ w/symbol.c
@@ -88,6 +88,7 @@ struct struct_union_info {
        unsigned long bit_size;
        int align_size;
        char has_flex_array;
+       char is_packed;
        struct symbol *flex_array;
 };

@@ -136,7 +137,10 @@ static void lay_out_struct(struct symbol *sym,
struct struct_union_info *info)
                info->flex_array = sym;
        }

-       align_bit_mask = bytes_to_bits(sym->ctype.alignment) - 1;
+       if (info->is_packed)
+               align_bit_mask = bytes_to_bits(1) - 1;
+       else
+               align_bit_mask = bytes_to_bits(sym->ctype.alignment) - 1;

        /*
         * Bitfields have some very special rules..
@@ -181,6 +185,8 @@ static struct symbol *
examine_struct_union_type(struct symbol *sym, int advance
        void (*fn)(struct symbol *, struct struct_union_info *);
        struct symbol *member;

+       info.is_packed = sym->ctype.modifiers & MOD_PACKED ? 1 : 0;
+
        fn = advance ? lay_out_struct : lay_out_union;
        FOR_EACH_PTR(sym->symbol_list, member) {
                if (member->ctype.base_type == &autotype_ctype) {
diff --git i/symbol.h w/symbol.h
index 5c5a7f12affa..172b70257d20 100644
--- i/symbol.h
+++ w/symbol.h
@@ -242,7 +242,7 @@ struct symbol {

 #define MOD_GNU_INLINE         0x00010000
 #define MOD_USERTYPE           0x00020000
-     // MOD UNUSED             0x00040000
+#define MOD_PACKED             0x00040000
      // MOD UNUSED             0x00080000
      // MOD UNUSED             0x00100000
      // MOD UNUSED             0x00200000


             reply	other threads:[~2020-12-15 18:16 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-15 18:15 Jacob Keller [this message]
2020-12-15 20:56 ` sparse attribute packed on structures Luc Van Oostenryck
2020-12-15 22:17   ` Jacob Keller
2020-12-15 22:44   ` Jacob Keller
2020-12-15 23:15   ` Jacob Keller
2020-12-16 23:30     ` Luc Van Oostenryck
2020-12-17  0:43       ` Jacob Keller
2020-12-17  0:57         ` Luc Van Oostenryck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0e8d816a-0849-c761-e0dc-93c3e5674e62@intel.com \
    --to=jacob.e.keller@intel.com \
    --cc=linux-sparse@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.