From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from eu-smtp-delivery-143.mimecast.com (eu-smtp-delivery-143.mimecast.com [207.82.80.143]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 490D81A1DF6 for ; Mon, 26 Sep 2016 07:39:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=armh.onmicrosoft.com; s=selector1-arm-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=ZCwxxLpr3XCxRg4Bhn47EXdbnVCMsooGQxesxaQ2NjI=; b=C/RIt2uT84s/XIza7Lwpi090lcrLZ3Bmb7Rxx6Qk4Zt+VSv++usyYfJxANU4ewEPd0qYd29rtPZcCCUjhoAOLaDlfV19SxB0w1587L0xcjVCbFjlYMKkMLH240pIuJrW9BHDXDgY6+efbenzjIx0gn/5u3ms28z2g9cmJEbojBk= Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-am5eur03lp0118.outbound.protection.outlook.com [213.199.154.118]) (Using TLS) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-50-i3yRUxIhPKqi2t4bC6AtwQ-1; Mon, 26 Sep 2016 15:39:47 +0100 Received: from AM5PR0801MB1955.eurprd08.prod.outlook.com (10.168.157.151) by AM5PR0801MB1953.eurprd08.prod.outlook.com (10.168.157.149) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.639.5; Mon, 26 Sep 2016 14:39:46 +0000 Received: from AM5PR0801MB1955.eurprd08.prod.outlook.com ([10.168.157.151]) by AM5PR0801MB1955.eurprd08.prod.outlook.com ([10.168.157.151]) with mapi id 15.01.0639.011; Mon, 26 Sep 2016 14:39:46 +0000 From: Alexei Fedorov To: "Cohen, Eugene" , "edk2-devel@lists.01.org" , "Kinney, Michael D" Thread-Topic: What is the right way to print a UINTN? Thread-Index: AdIX/FZUkJ+/GDfSRZe7u7ShyrQtxgAB1bdw Date: Mon, 26 Sep 2016 14:39:46 +0000 Message-ID: References: In-Reply-To: Accept-Language: en-GB, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [217.140.96.140] x-ms-office365-filtering-correlation-id: b2901111-3efb-45ac-1fa0-08d3e61af666 x-microsoft-exchange-diagnostics: 1; AM5PR0801MB1953; 20:rxWho/k69SPm4aUXXyqQ5P891bjMppEa0WBN7AyD6DhZ7H6lJ77XrOTqadJksonkKTjBEML4r0g4yqHZFnXZbRJTDY+cBZBVrvifjct4eZNFHm/Xo3TLMueNqXmDKemrhYQ3gC3cpvhhtfjFkR6PTgymT/Xop3lMM3CdXW2rP54= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:AM5PR0801MB1953; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(162533806227266); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6055026); SRVR:AM5PR0801MB1953; BCL:0; PCL:0; RULEID:; SRVR:AM5PR0801MB1953; x-forefront-prvs: 00770C4423 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(6009001)(7916002)(189002)(199003)(13464003)(40434004)(2950100002)(189998001)(5001770100001)(102836003)(586003)(68736007)(3846002)(2906002)(66066001)(97736004)(107886002)(3280700002)(54356999)(8936002)(76176999)(2501003)(7696004)(50986999)(3660700001)(5890100001)(92566002)(87936001)(101416001)(5660300001)(33656002)(7846002)(10400500002)(86362001)(122556002)(81166006)(6116002)(8676002)(76576001)(9686002)(19580395003)(19580405001)(106356001)(15975445007)(11100500001)(77096005)(8666005)(7736002)(74316002)(305945005)(5002640100001)(105586002)(2900100001)(81156014)(7059030)(43043002); DIR:OUT; SFP:1101; SCL:1; SRVR:AM5PR0801MB1953; H:AM5PR0801MB1955.eurprd08.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-originalarrivaltime: 26 Sep 2016 14:39:46.4145 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM5PR0801MB1953 X-MC-Unique: i3yRUxIhPKqi2t4bC6AtwQ-1 Subject: Re: What is the right way to print a UINTN? X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Sep 2016 14:39:51 -0000 Content-Language: en-US Content-Type: text/plain; charset=WINDOWS-1252 Content-Transfer-Encoding: quoted-printable I raised this issue a few years ago & was advised to use %p notation. Alexei. -----Original Message----- From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Cohe= n, Eugene Sent: 26 September 2016 14:46 To: edk2-devel@lists.01.org; Kinney, Michael D Subject: [edk2] What is the right way to print a UINTN? Get ready for a potentially stupid question (or at least a question I proba= bly should know the answer to by now)... The implementation of BasePrintLib treats types like %d and %x as the size = of the compiler's "int" type. On many 64-bit architectures the size of int= is 32-bits. On these same architectures we declare a "UINTN" type as 64-b= its. The handling for integral types (%d, %x, %u, etc) in BasePrintLib is as fol= lows, note the use of 'int': if (BaseListMarker =3D=3D NULL) { Value =3D VA_ARG (VaListMarker, int); } else { Value =3D BASE_ARG (BaseListMarker, int); } So it would seem to be improper to try to Print/DEBUG a UINTN value with %d= /%u/%x since the size will be mismatched on some architecture (INTN 64 bits= , int 32 bits). But it also would be improper to try to print this as %ld/= %lx because the size will be mismatched on 32-bit architectures (INTN 32 bi= ts and print will use a INT64 with the 'l' prefix). It's not obvious then = how to create a portable format specifier that works for UINTN. I did some research in how this is handled in edk2 for modules we know to b= e portable and I see multiple conflicting techniques being used. The predo= minant pattern for this is to try to print a UINTN parameter with the %d/%x= format specifier anyways like this: DEBUG ((EFI_D_ERROR, "FATAL ERROR - RaiseTpl with OldTpl(0x%x) > NewTpl(0= x%x)\n", OldTpl, NewTpl)); in this case the parameter if EFI_TPL which was typedef'ed as a UINTN. In = this case the compiler does the variadic thing and on a 64-bit architecture= puts a 64-bit UINTN on the variadic stack (using the term stack in the abs= tract sense here). When the print code tries to pop it off the stack using VA_ARG (VaListMarke= r, int) the 'int' gets upgraded in size to UINTN due to this construct in B= ase.h (I'm using GCC): #define VA_ARG(Marker, TYPE) ((sizeof (TYPE) < sizeof (UINTN)) ? = (TYPE)(__builtin_va_arg (Marker, UINTN)) : (TYPE)(__builtin_va_arg (Marker,= TYPE))) since sizeof(int) is 4 and this is less than sizeof(UINTN) at 8 the result = will be (TYPE)(__builtin_va_arg (Marker, UINTN)) where TYPE is 'int'. So = we end up popping 64-bits off the varidic stack but immediately typecast it= to an int (4 byte) resulting in loss of the upper-64 bits. If I'm reading= this right it means we can only print UINTNs whose value is below 2^32 (co= nfirmed with a debugger on AArch64 using GCC). Maybe this seems benign for= the simple EFI_TPL enumeration but if for some reason you add a new value = that exceeds 2^32-1 then the print code is broken. Is every user of Print/= DEBUG expected understand this range limitation? What is the preferred pattern for printing a INTN/UINTN then? Two yucky ha= cks I can think of: upcasting to UINT64/%ld when you "know" the value may e= xceed 2^32-1 or using %p for non-pointer types since this happens to get th= e right size treatment although we lose formatting options. Eugene _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel IMPORTANT NOTICE: The contents of this email and any attachments are confid= ential and may also be privileged. If you are not the intended recipient, p= lease notify the sender immediately and do not disclose the contents to any= other person, use it for any purpose, or store or copy the information in = any medium. Thank you.