diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-12-20 16:12:38 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2020-12-29 14:39:38 +0100 |
commit | f07a1053a90039a2d88ed62f74add2ee131d67b7 (patch) | |
tree | 805425a74adf49c8f6c74f853db71124f296bedd | |
parent | 09fcd53fd30883985aa5aeacc24808ba02fb7be1 (diff) | |
download | sparse-f07a1053a90039a2d88ed62f74add2ee131d67b7.tar.gz |
packed: no out-of-bound access of packed bitfields
There is (at least) 2 ways by which packed bitfields doesn't
follow normal layout/access rules and as consequence can't (always)
be accessed the usual way (load the whole underlying word, then shift
and mask to isolate the bitfield).
At least two different cases are a concern:
1) there is no padding at the end of a bitfield sequence. For example,
the following struct is only 3 bytes width:
struct s {
int f:24;
} __packed;
So, trying to access the bitfield by first doing a 32-bit load
will create an out-of-bound access.
2) a bitfield smaller than one word may need more than one word to be
accessed. For example, with the following struct
struct {
int a:5;
int f:30;
int z:5;
} __packed;
the bitfield 'f', while smaller than one 32-bit word, can't be accessed
with a single 32-bit access.
At machine level, these bitfields should be accessed with several, possibly
smaller, loads and their corresponding values reconstructed from these,
making things much more complicated than for non-packed bitfields.
But at IR level, things can be a little more flexible and things can stay
simple by using sub-word or super-word accesses (until these need to
be lowered to be usable at machine level). In other words, the example here
can be safely accessed with respectively a 24-bit and a 40-bit load.
This is what is done in this patch.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r-- | linearize.c | 13 | ||||
-rw-r--r-- | symbol.h | 1 |
2 files changed, 12 insertions, 2 deletions
diff --git a/linearize.c b/linearize.c index 0250c6bb..e80715ab 100644 --- a/linearize.c +++ b/linearize.c @@ -977,8 +977,17 @@ static struct symbol *bitfield_base_type(struct symbol *sym) if (sym) { if (sym->type == SYM_NODE) base = base->ctype.base_type; - if (base->type == SYM_BITFIELD) - return base->ctype.base_type; + if (base->type == SYM_BITFIELD) { + base = base->ctype.base_type; + if (sym->packed) { + int size = bits_to_bytes(sym->bit_offset + sym->bit_size); + sym = __alloc_symbol(0); + *sym = *base; + sym->bit_size = bytes_to_bits(size); + return sym; + } + return base; + } } return sym; } @@ -192,6 +192,7 @@ struct symbol { accessed:1, builtin:1, torename:1, + packed:1, transparent_union:1; int rank:3; // arithmetic's rank struct expression *array_size; |