Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Low: fix compiler's complaints about possibly unaligned pointer access #80

Closed
wants to merge 1 commit into from

Conversation

jnpkrn
Copy link

@jnpkrn jnpkrn commented Jan 15, 2020

In function ‘format_peers’: main.c:230:14:
warning: taking address of packed member of ‘struct booth_site’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
230 | localtime(&s->last_recv));
| ^~~~~~~~~~~~~
In function ‘booth_tcp_open’: transport.c:656:42:
warning: taking address of packed member of ‘struct booth_site’
may result in an unaligned pointer value [-Waddress-of-packed-member]
656 | rv = connect_nonb(s, (struct sockaddr *)&to->sa6, ..., ...);
| ^~~~~~~~
In function ‘message_recv’: transport.c:1108:7:
warning: taking address of packed member of ‘struct booth_site’
may result in an unaligned pointer value [-Waddress-of-packed-member]
1108 | time(&source->last_recv);
| ^~~~~~~~~~~~~~~~~~

and

In function ‘store_geo_attr’: attr.c:282:13:
warning: taking address of packed member of ‘struct geo_attr’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
282 | get_time(&a->update_ts);
| ^~~~~~~~~~~~~
timer.h:43:48: note: in definition of macro ‘get_time’
43 | #define get_time(p) clock_gettime(BOOTH_CLOCK, p)
| ^
In function ‘append_attr’: attr.c:337:18:
warning: taking address of packed member of ‘struct geo_attr’ may
result in an unaligned pointer value [-Waddress-of-packed-member]
337 | if (is_time_set(&a->update_ts)) {
| ^~~~~~~~~~~~~
attr.c:338:16: warning: taking address of packed member of
‘struct geo_attr’ may result in an unaligned pointer value
[-Waddress-of-packed-member]
338 | ts = wall_ts(&a->update_ts);
| ^~~~~~~~~~~~~

The solution for the affected, historically packed structs (which is
the trigger of the possible unaligned access in the first place),
assuming we want to carry on with this binary terseness, is that
we assure the struct itself is always aligned per its first member.
This first member is hence automatically guaranteed to be aligned
just as well, and shall there be any other address-of referenced
members, they immediately follow (rule being that these are ordered
from the biggest natural alignment to the lowest, for which C11
_Alignof operator is used).

We build on already established assumptions that data declarations
are readily controllable with non-standardized attribute annotations.
Shall this (or reliance on C11 construct, but hey, it's 2020) be in
violation with universality (it apparently hadn't been so far), both
"packed" and "aligned" are to be to be conditionally dropped together
(which will also restore no-complaints state as a side effect).

> In function ‘format_peers’: main.c:230:14:
> warning: taking address of packed member of ‘struct booth_site’ may
> result in an unaligned pointer value [-Waddress-of-packed-member]
>   230 |    localtime(&s->last_recv));
>       |              ^~~~~~~~~~~~~
> In function ‘booth_tcp_open’: transport.c:656:42:
> warning: taking address of packed member of ‘struct booth_site’
> may result in an unaligned pointer value [-Waddress-of-packed-member]
>   656 |  rv = connect_nonb(s, (struct sockaddr *)&to->sa6, ..., ...);
>       |                                          ^~~~~~~~
> In function ‘message_recv’: transport.c:1108:7:
> warning: taking address of packed member of ‘struct booth_site’
> may result in an unaligned pointer value [-Waddress-of-packed-member]
>  1108 |  time(&source->last_recv);
>       |       ^~~~~~~~~~~~~~~~~~

and

> In function ‘store_geo_attr’: attr.c:282:13:
> warning: taking address of packed member of ‘struct geo_attr’ may
> result in an unaligned pointer value [-Waddress-of-packed-member]
>   282 |    get_time(&a->update_ts);
>       |             ^~~~~~~~~~~~~
> timer.h:43:48: note: in definition of macro ‘get_time’
>    43 | #define get_time(p) clock_gettime(BOOTH_CLOCK, p)
>       |                                                ^
> In function ‘append_attr’: attr.c:337:18:
> warning: taking address of packed member of ‘struct geo_attr’ may
> result in an unaligned pointer value [-Waddress-of-packed-member]
>   337 |  if (is_time_set(&a->update_ts)) {
>       |                  ^~~~~~~~~~~~~
> attr.c:338:16: warning: taking address of packed member of
> ‘struct geo_attr’ may result in an unaligned pointer value
> [-Waddress-of-packed-member]
>   338 |   ts = wall_ts(&a->update_ts);
>       |                ^~~~~~~~~~~~~

The solution for the affected, historically packed structs (which is
the trigger of the possible unaligned access in the first place),
assuming we want to carry on with this binary terseness, is that
we assure the struct itself is always aligned per its first member.
This first member is hence automatically guaranteed to be aligned
just as well, and shall there be any other address-of referenced
members, they immediately follow (rule being that these are ordered
from the biggest natural alignment to the lowest, for which C11
_Alignof operator is used).

We build on already established assumptions that data declarations
are readily controllable with non-standardized attribute annotations.
Shall this (or reliance on C11 construct, but hey, it's 2020) be in
violation with universality (it apparently hadn't been so far), both
"packed" and "aligned" are to be to be conditionally dropped together
(which will also restore no-complaints state as a side effect).

Signed-off-by: Jan Pokorný <[email protected]>
@dmuhamedagic
Copy link

Thanks! I'd be all for dropping the packed attribute, either conditionally or altogether. The memory usage of booth is anyway very low.

@jnpkrn
Copy link
Author

jnpkrn commented Jan 21, 2020

That's also an option, thought that there was a reason and this would
be a minimal impact change in that regard.

Guess I will try to measure the impact of no/packing the structs
in practice and we'll see. All in all, that warning shall be
eliminated to prevent breakage on archs not supporting such
unaligned accesses (can generate SIGBUS for instance, from what
I've read).

Also, this is likely something that's relatively new in compiler
checks' arsenal (at least in that enabled by default) so this
must have been a pretty latent problem for ages.

@jnpkrn
Copy link
Author

jnpkrn commented Jan 27, 2020

Hm, on the second though, at least for struct booth_site, it
seems indeed like overly aggressive approach with packed attribute
(perhaps a matter of accidental cargo-culting from other places
in the project where it was justified).

So rather than to measure anything, I think the golden middle way is:

  1. drop packed attribute

  2. use pahole to verify there is rather little count of
    rather small holes in the struct (primarily on 64 bit arch),
    using common sense to settle on a reasonable trade-off
    vs. illogical grouping rather unrelated (semantically or
    per access pattern in code [data locality]) struct members
    (a.k.a. semi-packing by hand)

For struct geo_attr, just 1. would apply it seems.


Anyway, perhaps wouldn't be too bad, when at it, to also revisit
whether any packed structures have potential to impact cross-peer
interchange (ABI guarantees? mismatches amongst different archs
if/when explicit width integral types are not used?). No idea at
this moment, but looks like that compiler warning opened quite
some questions around what ramification are there, uncertain if
ever thought of before...

@jnpkrn
Copy link
Author

jnpkrn commented Apr 2, 2020

Sorry for keeping this around, this is subsumed in #82 that
still is to receive some more tweaks.

@jnpkrn jnpkrn closed this Apr 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants