svn commit: r269995 - projects/arm64/sys/arm64/include

Bruce Evans brde at optusnet.com.au
Fri Aug 15 01:34:56 UTC 2014


On Thu, 14 Aug 2014, Andrew Turner wrote:

> Log:
>  Fix the PRI*64 and SCN*64 macros. We use long long for 64-bit typedefs.

Why not fix the typedefs?  They should use the minimal rank that works,
although this gives the weirdness that intmax_t has lower rank than
long long.  All other 64-bit arches follow this rule.  Following this
rule minimises use of the long long abomination, and may expose broken
code slightly less.

> Modified: projects/arm64/sys/arm64/include/_inttypes.h
> ==============================================================================
> --- projects/arm64/sys/arm64/include/_inttypes.h	Thu Aug 14 18:44:08 2014	(r269994)
> +++ projects/arm64/sys/arm64/include/_inttypes.h	Thu Aug 14 18:46:30 2014	(r269995)
> @@ -42,32 +42,32 @@
> #define	PRId8		"d"	/* int8_t */
> #define	PRId16		"d"	/* int16_t */
> #define	PRId32		"d"	/* int32_t */
> -#define	PRId64		"ld"	/* int64_t */
> +#define	PRId64		"lld"	/* int64_t */

No one should notice this change, since the existence of PRI* is an even
larger bug than the existence of long long.

Broken code that might be exposed more by unnecessary use of long long
include things like hard-coding virtual addresses as u_long and printing
them with %lx.  This hard-coding works on all arches supported by FreeBSD.
However, FreeBSD is supposed to use vm_offset_t for virtual addresses, so
just printing them correcety requires casting to uintmax_t.  (One reason
the PRI* mistake is negatively useful is that converting from vm_offset_t
to a minimal type that works with PRI* is even harder that converting it
to a minimal basic types).  Most MD code doesn't bother with this, and
just hard-codes a format that works with the given arch.  E.g., in pmap.
vm_offset is normally defined as a uintN_t, so the rule about using the
minimal rank that works applies to it too.  E.g., on i386, uint32_t is
declared as u_int, not u_long.  This minimises unnecessary use of u_long.
Old code in i386 pmap depends on this -- it hard-codes the format as %x.
64-bit pmap normally hard-codes it as %lx instead.  arm64 would have to
use %llx instead.

Printf formats are relatively unimportant, especially in the kernel, and
wrong ones are not required to be detected, and the detection is even
more broken than it used to be since some compilers don't support
kernel format extensions and the "fix" for that is to turn off all
format checking.  You could get similar type errors that must be
detected by mixing APIs or hacking with u_long when you should really
use vm_offset_t.  One API might use vm_offset_t == uintN_t ==
[ u_long on all arches except arm64; u_long_long on arm64 ] and another
API might use u_long.  Then passing pointers between these APIs causes
type mismatches that must be detected if a prototype is in scope, although
everything is either 32 bits or 64 bits so there is no ABI mismatch.

Bruce


More information about the svn-src-projects mailing list