From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from NAM03-BY2-obe.outbound.protection.outlook.com (mail-by2nam03on072a.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe4a::72a]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id A46581A1E06 for ; Mon, 26 Sep 2016 06:46:22 -0700 (PDT) Received: from AT5PR84MB0291.NAMPRD84.PROD.OUTLOOK.COM (10.162.138.25) by AT5PR84MB0289.NAMPRD84.PROD.OUTLOOK.COM (10.162.138.23) 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 13:46:21 +0000 Received: from AT5PR84MB0291.NAMPRD84.PROD.OUTLOOK.COM ([10.162.138.25]) by AT5PR84MB0291.NAMPRD84.PROD.OUTLOOK.COM ([10.162.138.25]) with mapi id 15.01.0639.011; Mon, 26 Sep 2016 13:46:21 +0000 From: "Cohen, Eugene" To: "edk2-devel@lists.01.org" , "Kinney, Michael D" Thread-Topic: What is the right way to print a UINTN? Thread-Index: AdIX/FZUkJ+/GDfSRZe7u7ShyrQtxg== Date: Mon, 26 Sep 2016 13:46:21 +0000 Message-ID: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=eugene@hp.com; x-originating-ip: [15.65.252.13] x-ms-office365-filtering-correlation-id: d733dba6-e7be-4d96-c676-08d3e6137fec x-microsoft-exchange-diagnostics: 1; AT5PR84MB0289; 6:qPAy68uEmiT2oAUzecpjcg3Wt75IHioklJJiKL6Z8lKPX4p65GPMqkb90hPlifHVVq3qsXADOnzrmtxkzuOATuflD+BBVxSxgYEaSFbIiEzzzv/xdzAF1mzOQRNkQXW21tYIf9LBouFkHehlPYjKvi4CEQwe4NSfFUe33/cCHhMCa++gBMFZGA0V2BZ1WZwmNNyT7pyec8ZXEgC92fyrApzb81YVFWFJnIIJQ5iZ98Em3YK97oUY2N2U2Jf4WlG67/JtkXDzXX9kE71qf5oeA2RQDsX+ofe4LtdTkX/fnyY=; 5:nEqtZnnBf4neIyX0mlxG2z2cjcBKUCdEakv8R0TzNLvoUW382jpYwQeuZ49dyef9D/W2T6aqqQmtamJ4t1oGFFRZZCvc25GdReekVuXEbNCRmhkbiuJTUUmHCNWmA+yLb0i5S9RURqLyqy4j7WMbJg==; 24:4ZUALch2HF6++k9EAaGo3XjObIMbFGcI+aHbgbbXxG/yxO78EqyEM9onSZZ3T2+xQuRaweZcw30eRhc6SITe0zehHm/vbSqUwQCV44glVMc=; 7:MAXQ6BaCMZkq743gZwHyErLnbVVF1kuxVEnLq7OYpwtvF9fI3fnZ/MFrWKyBMoQLk6dxhdI6R1gfbk8k6BuNlEm/2JXgbwz0WMOHWxwcVJOzQM25P2M4OW9VLtfubxe5BB1s9x5TmkGnjX+BFmhf4+2Zl7dDzeEU5S9q92ebTpJt+1T39l6LT81XrvTOAxpnAlqnSbVWVzJg+QC08MEBpJz7f6gJpMVzTIIRsYE7VKJBr/mWjdinB5ePjAbGJ/Yr5Ioh67rTELUHnMdK78Axt9yKnR+9r0UT9NNQ0yhuVRCYYRWUyLYwC5mEdpFKXigT x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:AT5PR84MB0289; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046); SRVR:AT5PR84MB0289; BCL:0; PCL:0; RULEID:; SRVR:AT5PR84MB0289; x-forefront-prvs: 00770C4423 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(6009001)(7916002)(189002)(6602003)(199003)(97736004)(5001770100001)(3280700002)(81166006)(81156014)(66066001)(3846002)(586003)(102836003)(6116002)(77096005)(3660700001)(8676002)(2900100001)(8936002)(305945005)(11100500001)(7846002)(2501003)(106356001)(74316002)(107886002)(5002640100001)(229853001)(99286002)(105586002)(7736002)(33656002)(87936001)(189998001)(5660300001)(9686002)(54356999)(86362001)(7696004)(68736007)(122556002)(101416001)(2906002)(50986999)(92566002)(10400500002)(43043002); DIR:OUT; SFP:1102; SCL:1; SRVR:AT5PR84MB0289; H:AT5PR84MB0291.NAMPRD84.PROD.OUTLOOK.COM; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; received-spf: None (protection.outlook.com: hp.com does not designate permitted sender hosts) spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: hp.com X-MS-Exchange-CrossTenant-originalarrivaltime: 26 Sep 2016 13:46:21.1279 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: ca7981a2-785a-463d-b82a-3db87dfc3ce6 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AT5PR84MB0289 Subject: 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 13:46:22 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable 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