From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mailrelay.tugraz.at (mailrelay.tugraz.at [129.27.2.202]) by sourceware.org (Postfix) with ESMTPS id 8C148385AFAA for ; Tue, 18 Jul 2023 16:50:24 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 8C148385AFAA Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=tugraz.at Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tugraz.at Received: from vra-173-162.tugraz.at (vra-173-162.tugraz.at [129.27.173.162]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4R54gt30W4z1LM06; Tue, 18 Jul 2023 18:50:18 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 mailrelay.tugraz.at 4R54gt30W4z1LM06 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tugraz.at; s=mailrelay; t=1689699019; bh=Du9Gs+gsj5vtQdJalgzBDwYnUUvLX51Vw3BmNrmFlkk=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=XuUkOPdFkit3jf3c5TMJuMyjw/9r7DCdJ0xqUbDoZfODgLYlj4VETrvY+tS4w0GtK ZjJlI2jLxpEHwGXdwrg1DUAYU0UVzDJyoY13mLVU78uS864tYDR1Bw36fn1qq9YXmg B9uIsF/1bz/Nx2+NU1ekj6b9C/82htvYI+UHeIJ8= Message-ID: <62d781156fd98afd70a26dbed028f868360b25c5.camel@tugraz.at> Subject: Re: [V1][PATCH 0/3] New attribute "element_count" to annotate bounds for C99 FAM(PR108896) From: Martin Uecker To: Qing Zhao Cc: Kees Cook , Siddhesh Poyarekar , Jakub Jelinek , "joseph@codesourcery.com" , "richard.guenther@gmail.com" , "gcc-patches@gcc.gnu.org" , "isanbard@gmail.com" Date: Tue, 18 Jul 2023 18:50:17 +0200 In-Reply-To: <47420B99-41F3-4714-92A5-24722BDC9CBC@oracle.com> References: <20230525161450.3704901-1-qing.zhao@oracle.com> <202305261218.2420AB8E0@keescook> <202307131311.1F30C4357@keescook> <202307171612.406D82C39@keescook> <09305AA9-5D15-4DD6-8C9D-5FD5F0EC09ED@oracle.com> <08cc59da30d4a4c5b4df6b294051bad43a35a0a1.camel@tugraz.at> <47420B99-41F3-4714-92A5-24722BDC9CBC@oracle.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.46.4-2 MIME-Version: 1.0 X-TUG-Backscatter-control: G/VXY7/6zeyuAY/PU2/0qw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -0.4 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.117 X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,BODY_8BITS,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,KAM_SHORT,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Am Dienstag, dem 18.07.2023 um 16:25 +0000 schrieb Qing Zhao: >=20 >=20 > > On Jul 18, 2023, at 12:03 PM, Martin Uecker > > wrote: > >=20 > > Am Dienstag, dem 18.07.2023 um 15:37 +0000 schrieb Qing Zhao: > > >=20 > > >=20 > > > > On Jul 17, 2023, at 7:40 PM, Kees Cook > > > > wrote: > > > >=20 > > > > On Mon, Jul 17, 2023 at 09:17:48PM +0000, Qing Zhao wrote: > > > > >=20 > > > > > > On Jul 13, 2023, at 4:31 PM, Kees Cook > > > > > > > > > > > > wrote: > > > > > >=20 > > > > > > In the bug, the problem is that "p" isn't known to be > > > > > > allocated, if I'm > > > > > > reading that correctly? > > > > >=20 > > > > > I think that the major point in PR109557 > > > > > (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D109557): > > > > >=20 > > > > > for the following pointer p.3_1,=20 > > > > >=20 > > > > > p.3_1 =3D p; > > > > > _2 =3D __builtin_object_size (p.3_1, 0); > > > > >=20 > > > > > Question: why the size of p.3_1 cannot use the TYPE_SIZE of > > > > > the > > > > > pointee of p when the TYPE_SIZE can be determined at compile > > > > > time? > > > > >=20 > > > > > Answer:=C2=A0 From just knowing the type of the pointee of p, the > > > > > compiler cannot determine the size of the object.=C2=A0=20 > > > >=20 > > > > Why is that? "p" points to "struct P", which has a fixed size. > > > > There > > > > must be an assumption somewhere that a pointer is allocated, > > > > otherwise > > > > __bos would almost never work? > > >=20 > > > My understanding from the comments in PR109557 was:=20 > > >=20 > > > In general the pointer could point to the first object of an > > > array > > > that has more elements, or to an object of a different type.=20 > > > Without seeing the real allocation to the pointer, the compiler > > > cannot assume that the pointer point to an object that has > > > the exact same type as its declaration.=20 > > >=20 > > > Sid and Martin, is the above understand correctly? > >=20 > > Yes.=20 > >=20 > > In the example, it *could* work because the compiler > > could inline 'store' or otherwise use its knowledge about > > the function definition to conclude that 'p' points to > > an object of size 'sizeof (struct P)'. But this is fragile > > because it relies on optimization and will not work across > > TUs. > >=20 > > > Honestly, I am still not 100% clear on this yet. > >=20 > > > Jakub, Sid and Martin, could=C2=A0 you please explain a little bit > > > more > > > here, especially for the following small example? > > >=20 > > > [opc@qinzhao-ol8u3-x86 109557]$ cat t.c > > > #include > > > #include > > > struct P { > > > =C2=A0 int k; > > > =C2=A0 int x[10];=20 > > > } *p; > > >=20 > > > void store(int a, int b)=20 > > > { > > > =C2=A0 p =3D (struct P *)malloc (sizeof (struct P)); > > > =C2=A0 p->k =3D a; > > > =C2=A0 p->x[b] =3D 0; > > > =C2=A0 assert (__builtin_dynamic_object_size (p->x, 1) =3D=3D sizeof > > > (int[10])); > > > =C2=A0 assert (__builtin_dynamic_object_size (p, 1) =3D=3D sizeof (st= ruct > > > P)); > > > =C2=A0 return; > > > } > > >=20 > > > int main() > > > { > > > =C2=A0 store(7, 7); > > > =C2=A0 assert (__builtin_dynamic_object_size (p->x, 1) =3D=3D sizeof > > > (int[10])); > > > =C2=A0 assert (__builtin_dynamic_object_size (p, 1) =3D=3D sizeof (st= ruct > > > P)); > > > =C2=A0 free (p); > > > } > > > [opc@qinzhao-ol8u3-x86 109557]$ sh t > > > /home/opc/Install/latest/bin/gcc -O -fdump-tree-all t.c > > > a.out: t.c:21: main: Assertion `__builtin_dynamic_object_size (p- > > > >x, > > > 1) =3D=3D sizeof (int[10])' failed. > > > t: line 19: 859944 Aborted=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (core dumped) ./a.ou= t > > >=20 > > >=20 > > > In the above, among the 4 assertions, only the last one failed. > >=20 > > I don't know why this is the case.=20 > >=20 > > >=20 > > > Why GCC can use the TYPE_SIZE of the pointee of the pointer =E2=80=9C= p- > > > >x=E2=80=9D as > > > the size of the object,=20 > >=20 > > I do not think it can do this in general. Is this how it=20 > > is implemented? >=20 > No. -:) >=20 > =C2=A0I guess that the implementation of this should base on your > following case,=C2=A0 =E2=80=9Cobserved accesses=E2=80=9D: > Although I am not 100% sure on the definition of =E2=80=9Cobserved access= es=E2=80=9D. >=20 > p->x=C2=A0 is an access to the field of the object, so compiler can assum= e > that the object exist and have > the type associate with this access? >=20 Only if the access happens at run-time, but the argument to BDOS is not evaluated, so there is no access. At least, this is my guess based=C2= =A0 on C's semantics.=20 > On the other hand, =E2=80=9Cp=E2=80=9D is just a plain pointer, no observ= ed access. > > > Thus would then seem incorrect to me.=C2=A0=20 > >=20 > > > but cannot use the TYPE_SIZE of the pointee of the pointer =E2=80=9Cp= =E2=80=9D as > > > the > > > size of the object?=20 > >=20 > > In general, the type of a pointer does not say anything about the > > object it points to, because you could cast the pointer to a > > different > > type, pass it around, and then cast it back before use.=20 >=20 > Okay, I see. > >=20 > > Only observed allocations or observed accesses provide information > > about the type / existence of an object at the corresponding > > address. >=20 > What will be included in =E2=80=9Cobserved accesses=E2=80=9D? Any read or write access can be used to determine that there must be an object of the corresponding type at this location. (A write access could possibly create an object.) This still does not tell one anything about the size of the storage region, because it could be larger than one object of this type.=20 Martin > >=20 > > The only other way in C which ensures that a pointer actually > > points > > to an object of the correct type is 'static': > >=20 > > void foo(struct P *p[static 1]); >=20 > Thanks for the info. >=20 > Qing > >=20 > >=20 > >=20 > > Martin > >=20 > >=20 > > >=20 > > > >=20 > > > > > Therefore the bug has been closed.=20 > > > > >=20 > > > > > In your following testing 5: > > > > >=20 > > > > > > I'm not sure this is a reasonable behavior, but > > > > > > let me get into the specific test, which looks like this: > > > > > >=20 > > > > > > TEST(counted_by_seen_by_bdos) > > > > > > { > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct annotated *p; > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int index =3D MAX_INDEX + uncons= t; > > > > > >=20 > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 p =3D alloc_annotated(index); > > > > > >=20 > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 REPORT_SIZE(p->array); > > > > > > /* 1 */ EXPECT_EQ(sizeof(*p), offsetof(typeof(*p), array)); > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Check array size alone. */ > > > > > > /* 2 */ EXPECT_EQ(__builtin_object_size(p->array, 1), > > > > > > SIZE_MAX); > > > > > > /* 3 */ EXPECT_EQ(__builtin_dynamic_object_size(p->array, > > > > > > 1), > > > > > > p->foo * sizeof(*p->array)); > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Check check entire object siz= e. */ > > > > > > /* 4 */ EXPECT_EQ(__builtin_object_size(p, 1), SIZE_MAX); > > > > > > /* 5 */ EXPECT_EQ(__builtin_dynamic_object_size(p, 1), > > > > > > sizeof(*p) + p->foo * sizeof(*p->array)); > > > > > > } > > > > > >=20 > > > > > > Test 5 should pass as well, since, again, p can be > > > > > > examined. > > > > > > Passing p > > > > > > to __bdos implies it is allocated and the __counted_by > > > > > > annotation can be > > > > > > examined. > > > > >=20 > > > > > Since the call to the routine =E2=80=9Calloc_annotated" cannot be > > > > > inlined, GCC does not see any allocation calls for the > > > > > pointer p. > > > >=20 > > > > Correct. > > > >=20 > > > > > At the same time, due to the same reason as PR109986, GCC > > > > > cannot > > > > > determine the size of the object by just knowing the > > > > > TYPE_SIZE > > > > > of the pointee of p.=C2=A0=20 > > > >=20 > > > > So the difference between test 3 and test 5 is that "p" is > > > > explicitly > > > > dereferenced to find "array", and therefore an assumption is > > > > established > > > > that "p" is allocated? > > >=20 > > > Yes, this might be the assumption that GCC made=C2=A0 -:) > > > >=20 > > > > > So, this is exactly the same issue as PR109557.=C2=A0 It=E2=80=99= s an > > > > > existing > > > > > behavior per the current __buitlin_object_size algorithm. > > > > > I am still not very sure whether the situation in PR109557 > > > > > can be > > > > > improved or not, but either way, it=E2=80=99s a separate issue. > > > >=20 > > > > Okay, so the issue is one of object allocation visibility (or > > > > assumptions there in)? > > >=20 > > > Might be, let=E2=80=99s see what Sid or Martin will say on this. > > > >=20 > > > > > Please see the new testing case I added for PR109557, you > > > > > will > > > > > see that the above case 5 is a similar case as the new > > > > > testing > > > > > case in PR109557. > > > >=20 > > > > I will ponder this a bit more to see if I can come up with a > > > > useful > > > > test case to replace the part from "test 5" above. > > > >=20 > > > > > >=20 > > > > > > If "return p->array[index];" would be caught by the > > > > > > sanitizer, > > > > > > then > > > > > > it follows that __builtin_dynamic_object_size(p, 1) must > > > > > > also > > > > > > know the > > > > > > size. i.e. both must examine "p" and its trailing flexible > > > > > > array and > > > > > > __counted_by annotation. > > > > > >=20 > > > > > > >=20 > > > > > > > 2. The common issue for=C2=A0 the failed testing 3, 4, 9, 10 > > > > > > > is: > > > > > > >=20 > > > > > > > for the following annotated structure:=20 > > > > > > >=20 > > > > > > > =3D=3D=3D=3D > > > > > > > struct annotated { > > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unsigned long flags; > > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 size_t foo; > > > > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int array[] __attribute__((cou= nted_by (foo))); > > > > > > > }; > > > > > > >=20 > > > > > > >=20 > > > > > > > struct annotated *p; > > > > > > > int index =3D 16; > > > > > > >=20 > > > > > > > p =3D malloc(sizeof(*p) + index * sizeof(*p->array));=C2=A0 /= / > > > > > > > allocated real size=20 > > > > > > >=20 > > > > > > > p->foo =3D index + 2;=C2=A0 // p->foo was set by a different > > > > > > > value > > > > > > > than the real size of p->array as in test 9 and 10 > > > > > >=20 > > > > > > Right, tests 9 and 10 are checking that the _smallest_ > > > > > > possible > > > > > > value of > > > > > > the array is used. (There are two sources of information: > > > > > > the > > > > > > allocation > > > > > > size and the size calculated by counted_by. The smaller of > > > > > > the > > > > > > two > > > > > > should be used when both are available.) > > > > >=20 > > > > > The counted_by attribute is used to annotate a Flexible array > > > > > member on how many elements it will have. > > > > > However, if this information can not accurately reflect the > > > > > real > > > > > number of elements for the array allocated,=20 > > > > > What=E2=80=99s the purpose of such information?=20 > > > >=20 > > > > For example, imagine code that allocates space for 100 elements > > > > since > > > > the common case is that the number of elements will grow over > > > > time. > > > > Elements are added as it goes. For example: > > > >=20 > > > > struct grows { > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int alloc_count; > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int valid_count; > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct element item[] __= counted_by(valid_count); > > > > } *p; > > > >=20 > > > > void something(void) > > > > { > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 p =3D malloc(sizeof(*p) = + sizeof(*p->item) * 100); > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 p->alloc_count =3D 100; > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 p->valid_count =3D 0; > > > >=20 > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* this loop doesn't che= ck that we don't go over 100. > > > > */ > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 while (items_to_copy) { > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 struct element *item_ptr =3D get_next_item(); > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 /* __counted_by stays in sync: */ > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 p->valid_count++; > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0 p->item[p->valid_count - 1] =3D *item_ptr; > > > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } > > > > } > > > >=20 > > > > We would want to catch cases there p->item[] is accessed with > > > > an > > > > index > > > > that is >=3D p->valid_count, even though the allocation is > > > > (currently) > > > > larger. > > > >=20 > > > > However, if we ever reached valid_count >=3D alloc_count, we need > > > > to > > > > trap > > > > too, since we can still "see" the true allocation size. > > > >=20 > > > > Now, the __alloc_size hint is visible in very few places, so if > > > > there is > > > > a strong reason to do so, I can live with saying that > > > > __counted_by > > > > takes > > > > full precedence over __alloc_size. It seems it should be > > > > possible > > > > to > > > > compare when both are present, but I can live with __counted_by > > > > being > > > > the universal truth. :) > > > >=20 > > >=20 > > > Thanks for the example and the explanation. Understood now. > > >=20 > > > LLVM=E2=80=99s RFC requires the following relationship: > > > ( > > > https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-c-fbou > > > nd > > > s-safety/70854#maintaining-correctness-of-bounds-annotations-18) > > >=20 > > > Buffer=E2=80=99s real allocated size >=3D counted_by value > > >=20 > > > Should be true all the time.=20 > > >=20 > > > I think that this is a reasonable requirement.=20 > > >=20 > > > (Otherwise, if counted_by > buffer=E2=80=99s real allocated size, > > > overflow > > > might happen) > > >=20 > > > Is the above enough to cover your use cases? > > >=20 > > > If so, I will study a little bit more to see how to implement > > > this. > > > > >=20 > > > > > > > or > > > > > > > p->foo was not set to any value as in test 3 and 4 > > > > > >=20 > > > > > > For tests 3 and 4, yes, this was my mistake. I have fixed > > > > > > up > > > > > > the tests > > > > > > now. Bill noticed the same issue. Sorry for the think-o! > > > > > >=20 > > > > > > > =3D=3D=3D=3D > > > > > > >=20 > > > > > > > i.e, the value of p->foo is NOT synced with the number of > > > > > > > elements allocated for the array p->array.=C2=A0=20 > > > > > > >=20 > > > > > > > I think that this should be considered as an user error, > > > > > > > and > > > > > > > the documentation of the attribute should include > > > > > > > this requirement.=C2=A0 (In the LLVM=E2=80=99s RFC, such requ= irement > > > > > > > was > > > > > > > included in the programing model:=20 > > > > > > > https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-c= -fbounds-safety/70854#maintaining-correctness-of-bounds-annotations-18 > > > > > > > ) > > > > > > >=20 > > > > > > > We can add a new warning option -Wcounted-by to report > > > > > > > such > > > > > > > user error if needed. > > > > > > >=20 > > > > > > > What=E2=80=99s your opinion on this? > > > > > >=20 > > > > > > I think it is correct to allow mismatch between allocation > > > > > > and > > > > > > counted_by as long as only the least of the two is used. > > > > >=20 > > > > > What=E2=80=99s your mean by =E2=80=9Conly the least of the two is= used=E2=80=9D? > > > >=20 > > > > I was just restating the above: if size information is > > > > available > > > > via > > > > both __alloc_size and __counted_by, the smaller of the two > > > > should > > > > be > > > > used. > > >=20 > > > If we are consistent with LLVM=E2=80=99s RFC, __alloc_size >=3D > > > __counted_by > > > all the time. > > > Then we can always use the counted_by info for the array size.=20 > > > >=20 > > > > >=20 > > > > > > This may be > > > > > > desirable in a few situations. One example would be a large > > > > > > allocation > > > > > > that is slowly filled up by the program. > > > > >=20 > > > > > So, for such situation, whenever the allocation is filled up, > > > > > the > > > > > field that hold the =E2=80=9Ccounted_by=E2=80=9D attribute should= be > > > > > increased at > > > > > the same time, > > > > > Then, the =E2=80=9Ccounted_by=E2=80=9D value always sync with the= real > > > > > allocation.=20 > > > > > > I.e. the counted_by member is > > > > > > slowly increased during runtime (but not beyond the true > > > > > > allocation size). > > > > >=20 > > > > > Then there should be source code to increase the =E2=80=9Ccounted= _by=E2=80=9D > > > > > field whenever the allocated space increased too.=20 > > > > > >=20 > > > > > > Of course allocation size is only available in limited > > > > > > situations, so > > > > > > the loss of that info is fine: we have counted_by for > > > > > > everything else. > > > > >=20 > > > > > The point is: allocation size should synced with the value of > > > > > =E2=80=9Ccounted_by=E2=80=9D. LLVM=E2=80=99s RFC also have the si= milar requirement: > > > > > https://discourse.llvm.org/t/rfc-enforcing-bounds-safety-in-c-fbo= unds-safety/70854#maintaining-correctness-of-bounds-annotations-18 > > > >=20 > > > > Right, I'm saying it would be nice if __alloc_size was checked > > > > as > > > > well, > > > > in the sense that if it is available, it knows without question > > > > what the > > > > size of the allocation is. If __alloc_size and __counted_by > > > > conflict, > > > > the smaller of the two should be the truth. > > >=20 > > > >=20 > > > > But, as I said, if there is some need to explicitly ignore > > > > __alloc_size > > > > when __counted_by is present, I can live with it; we just need > > > > to > > > > document it. > > > >=20 > > > > If the RFC and you agree that the __counted_by variable can > > > > only > > > > ever be > > > > (re)assigned after the flex array has been (re)allocated, then > > > > I > > > > guess > > > > we'll see how it goes. :) I think most places in the kernel > > > > using > > > > __counted_by will be fine, but I suspect we may have cases > > > > where we > > > > need > > > > to update it like in the loop I described above. If that's > > > > true, we > > > > can > > > > revisit the requirement then. :) > > >=20 > > > I guess if we can always keep=C2=A0 the relationship:=C2=A0=C2=A0 __a= lloc_size > > > >=3D > > > __counted_by all the time. Should be fine. > > >=20 > > > Please check whether this is enough for kernel, I will check > > > whether > > > this is doable For GCC. > > >=20 > > > thanks. > > >=20 > > >=20 > > > Qing > > > >=20 > > > > -Kees > > > >=20 > > > > --=20 > > > > Kees Cook > > >=20 > >=20 > > --=20 > > Univ.-Prof. Dr. rer. nat. Martin Uecker > > Graz University of Technology > > Institute of Biomedical Imaging >=20 --=20 Univ.-Prof. Dr. rer. nat. Martin Uecker Graz University of Technology Institute of Biomedical Imaging