> On Dec 7, 2024, at 03:57, Martin Uecker <[email protected]> wrote:
>
> Am Freitag, dem 06.12.2024 um 16:13 +0000 schrieb Qing Zhao:
>>
>>> On Dec 6, 2024, at 10:56, Martin Uecker <[email protected]> wrote:
>>>
>>> Am Freitag, dem 06.12.2024 um 14:16 +0000 schrieb Qing Zhao:
>>>>
>
> ...
>
>>>>>
>>>>> I think the relevant scenario is where you assign the struct and
>>>>> not a pointer to the struct, i.e. something like the following:
>>>>>
>>>>> #include "builtin-object-size-common.h"
>>>>>
>>>>> struct annotated {
>>>>> int b;
>>>>> int *c __attribute__ ((counted_by (b)));
>>>>> };
>>>>>
>>>>> struct annotated __attribute__((__noinline__)) setup (int attr_count)
>>>>> {
>>>>> struct annotated p_array_annotated;
>>>>> p_array_annotated.c = (int *) malloc (sizeof (int) * attr_count);
>>>>> p_array_annotated.b = attr_count;
>>>>>
>>>>> return p_array_annotated;
>>>>> }
>>>>>
>>>>>
>>>>> int main(int argc, char *argv[])
>>>>> {
>>>>> struct annotated x = setup (10);
>>>>> int *p = x.c;
>>>>> x = setup (20);
>>>>> EXPECT(__builtin_dynamic_object_size (p, 1), 10 * sizeof (int));
>>>>> EXPECT(__builtin_dynamic_object_size (x.c, 1), 20 * sizeof (int));
>>>>> DONE ();
>>>>> }
>>>>>
>>>>
>>>> With the above testing case, my current implementation based on
>>>> .ACCESS_WITH_SIZE succeed without any issue. -:)
>>>> The design of .ACCESS_WITH_SIZE already resolved this issue.
>>>
>>> Ok, thanks! But I am a bit confused, because it seems it behaves
>>> this way also for FAMs
>>>
>>> https://godbolt.org/z/64a6z4cna
>>
>> The behavior of the above testing case is exactly the additional feature we
>> provided for counted_by attribute for FAM:
>>
>> =====
>> One important feature of the attribute is, a reference to the
>> flexible array member field uses the latest value assigned to the
>> field that represents the number of the elements before that
>> reference. For example,
>>
>> p->count = val1;
>> p->array[20] = 0; // ref1 to p->array
>> p->count = val2;
>> p->array[30] = 0; // ref2 to p->array
>>
>> in the above, 'ref1' uses 'val1' as the number of the elements in
>> 'p->array', and 'ref2' uses 'val2' as the number of elements in
>> 'p->array’.
>> =====
>>
>> So, it’s the correct behavior for the counted_by attribute for FAM based on
>> our previous discussion and agreement.
>
> If it is indeed that the value of p->count last stored before p->array is
> *referenced* which counts, then everything is well.
Yes, For FAM, every “reference” to p->array will be converted as a call to
(*.ACCESS_WITH_SIZE (p->array, &p->count, …))
The count value for p->array is *(&p->count), which is guaranteed to be the
last stored value of the address of p->count before the current reference to
p->array.
Similarly, for the pointer array, every “reference” to p->pa will be converted
as a call to .ACCESS_WITH_SIZE(p->pa, &p->count…). The count value of the
pointer array p->pa is *(&p->count), which is also guaranteed to be the last
stored value of the address of p->count before the current reference to p->pa.
> Somehow I thought for FAMs it is the value p->count last stored before
> p->array is *accessed* (possibly indirectly via another pointer). Probably
> it was just me being confused.
>
>>
>> However, as you pointed out, when the “counted_by” attribute is extended to
>> the pointer field, this feature will be problematic.
>> And we need to add the following additional new requirement for the
>> “counted_by” attribute of pointer field:
>>
>> p->count and p->array can only be changed by changing the whole structure
>> at the same time.
>
> Actually, I am then not even sure we need this requirement. My point was only
> that
> setting the whole structure at the time should work correctly, i.e. without
> changing
> the bounds for old pointers which were stored in the struct previously. With
> the
> semantics above it seems this case also works automatically.
For pointer field with counted_by attribute, if the p->count and p->pa are not
set together when changing the whole structure, then for example:
struct annotated {
int b;
int *c __attribute__ ((counted_by (b)));
};
/* note, this routine only allocate the space for the pointer array field, but
does NOT set the counted_by field. */
struct annotated __attribute__((__noinline__)) setup (int attr_count)
{
struct annotated p_array_annotated;
p_array_annotated.c = (int *) malloc (sizeof (int) * attr_count);
return p_array_annotated;
}
int main(int argc, char *argv[])
{
struct annotated x = setup (10);
x.b = 10; /* the counted_by is set here. */
int *p = x.c; /* x.c’s count should be 10, which is correct. */
x = setup (20);
__builtin_dynamic_object_size (x.c, 1); /* x.c’s count now should be 20, but
it’s not set yet, the object size is unknown at this moment. Shall we ask the
user to always set the counted_by value when the corresponding pointer is
changed? */
}
thanks.
Qing
>
> Martin
>
>>
>> So for a structure that includes a pointer field with a counted_by
>> attribute, the p->count and p->array must be updated at the same time by
>> changing the whole structure, therefore the testing case will not be valid
>> for pointer field, we MUST change it as the following to make it valid for
>> pointer field with counted_by attribute:
>>
>> int main(int argc, char *argv[])
>> {
>> struct annotated *x = setup(10);
>> int *p = x->c;
>> x = setup(5);
>> printf("%d\n", (int)__builtin_dynamic_object_size (p, 1));
>> printf("%d\n", (int)__builtin_dynamic_object_size (x->c, 1));
>> exit(0);
>> }
>>
>>
>> Hope this is clear this time -:).
>
>
>>
>> Qing
>>>
>>> and I thought this was changed, i.e. so that the bounds
>>> track the current value of b for this case. But apparently
>>> I was mistaken. I am fine with the behavior as shown here.
>>>
>>> Martin
>>>
>>>>
>>>> Qing
>>>>> Martin
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>> --
>>> Univ.-Prof. Dr. rer. nat. Martin Uecker
>>> Graz University of Technology
>>> Institute of Biomedical Imaging