Bug 28073 - [libabigail] Incorrect size for bitfields
Summary: [libabigail] Incorrect size for bitfields
Status: RESOLVED FIXED
Alias: None
Product: libabigail
Classification: Unclassified
Component: default (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: ---
Assignee: Dodji Seketeli
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-07-10 19:27 UTC by David Marchand
Modified: 2021-12-06 13:54 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
after_plop.dump (702 bytes, text/plain)
2021-07-10 19:27 UTC, David Marchand
Details

Note You need to log in before you can comment on or make changes to this bug.
Description David Marchand 2021-07-10 19:27:33 UTC
Created attachment 13555 [details]
after_plop.dump

This is a continuation of #28060 with a little extension on the reproducer, adding a other field at the end of the struct.

$ cat plop.c
#include <inttypes.h>

struct bigstruct {
	char name[128];
	uint8_t bitfield0:1
#ifndef BEFORE
	        ,bitfield1:1
#endif
	;
	uint8_t other;
};

void access_bigstruct(struct bigstruct *st)
{
#ifndef BEFORE
	st->bitfield1 = 1;
#endif
}

XML dump is attached.

As far as I can see, the bitfield0 and bitfield1 are declared with a uint8_t type, of size 8 bits.
[...]
    <type-decl name='unsigned char' size-in-bits='8' id='type-id-5'/>
[...]
      <data-member access='public' layout-offset-in-bits='7'>
        <var-decl name='bitfield0' type-id='type-id-8' visibility='default' filepath='/home/dmarchan/libabigail_bitfields/plop.c' line='5' column='1'/>
      </data-member>
      <data-member access='public' layout-offset-in-bits='6'>
        <var-decl name='bitfield1' type-id='type-id-8' visibility='default' filepath='/home/dmarchan/libabigail_bitfields/plop.c' line='7' column='1'/>
      </data-member>
[...]
    <typedef-decl name='uint8_t' type-id='type-id-9' filepath='/usr/include/bits/stdint-uintn.h' line='24' column='1' id='type-id-8'/>
    <typedef-decl name='__uint8_t' type-id='type-id-5' filepath='/usr/include/bits/types.h' line='38' column='1' id='type-id-9'/>
[...]


This makes it impossible to write a suppression rule based on, for example, bitfield0 offset.
[suppress_type]
	name = bigstruct
	has_data_member_inserted_between = {offset_after(bitfield0), offset_of(other)}
Comment 1 Dodji Seketeli 2021-12-06 13:54:07 UTC
I think the correct suppression specification for this should be:

1/
[suppress_type]
	name = bigstruct
	has_data_member_inserted_between = {offset_of(bitfield0), offset_of(other)}

Why?

because offset_after(bitfield0) means the offset of the data member that comes after bitfiled0, in the initial version of the type.  In that version, the data member that comes after the data member "bitfield0" is the data member "other".

So, {offset_after(bitfield0), offset_of(other)} is equivalent to:
{offset_of(other), offset_of(other)}.  And that is not what we want.

The code that evaluates the suppression specification, however, has a tangentially related flaw:  If bitfield0 is later removed, the suppression specification 1/ should not suppress that removal change.  That flaw is now fixed by the commit https://sourceware.org/git/?p=libabigail.git;a=commit;h=3e0eeb9f98216ecd1c3224f687fe1e1ef72b56e4 which also updates the documentation of to clarify the use of the has_data_member_inserted_between property.