* What is the right way to print a UINTN?
@ 2016-09-26 13:46 Cohen, Eugene
2016-09-26 14:39 ` Alexei Fedorov
2016-09-26 15:31 ` Laszlo Ersek
0 siblings, 2 replies; 16+ messages in thread
From: Cohen, Eugene @ 2016-09-26 13:46 UTC (permalink / raw)
To: edk2-devel@lists.01.org, Kinney, Michael D
Get ready for a potentially stupid question (or at least a question I probably 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-bits.
The handling for integral types (%d, %x, %u, etc) in BasePrintLib is as follows, note the use of 'int':
if (BaseListMarker == NULL) {
Value = VA_ARG (VaListMarker, int);
} else {
Value = 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 bits 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 be portable and I see multiple conflicting techniques being used. The predominant 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(0x%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 abstract sense here).
When the print code tries to pop it off the stack using VA_ARG (VaListMarker, int) the 'int' gets upgraded in size to UINTN due to this construct in Base.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 (confirmed 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 hacks I can think of: upcasting to UINT64/%ld when you "know" the value may exceed 2^32-1 or using %p for non-pointer types since this happens to get the right size treatment although we lose formatting options.
Eugene
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-26 13:46 What is the right way to print a UINTN? Cohen, Eugene
@ 2016-09-26 14:39 ` Alexei Fedorov
2016-09-26 15:31 ` Laszlo Ersek
1 sibling, 0 replies; 16+ messages in thread
From: Alexei Fedorov @ 2016-09-26 14:39 UTC (permalink / raw)
To: Cohen, Eugene, edk2-devel@lists.01.org, Kinney, Michael D
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 Cohen, 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 probably 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-bits.
The handling for integral types (%d, %x, %u, etc) in BasePrintLib is as follows, note the use of 'int':
if (BaseListMarker == NULL) {
Value = VA_ARG (VaListMarker, int);
} else {
Value = 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 bits 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 be portable and I see multiple conflicting techniques being used. The predominant 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(0x%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 abstract sense here).
When the print code tries to pop it off the stack using VA_ARG (VaListMarker, int) the 'int' gets upgraded in size to UINTN due to this construct in Base.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 (confirmed 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 hacks I can think of: upcasting to UINT64/%ld when you "know" the value may exceed 2^32-1 or using %p for non-pointer types since this happens to get the 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 confidential and may also be privileged. If you are not the intended recipient, please 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.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-26 13:46 What is the right way to print a UINTN? Cohen, Eugene
2016-09-26 14:39 ` Alexei Fedorov
@ 2016-09-26 15:31 ` Laszlo Ersek
2016-09-27 12:29 ` Cohen, Eugene
1 sibling, 1 reply; 16+ messages in thread
From: Laszlo Ersek @ 2016-09-26 15:31 UTC (permalink / raw)
To: Cohen, Eugene; +Cc: edk2-devel@lists.01.org, Kinney, Michael D, Alexei Fedorov
On 09/26/16 15:46, Cohen, Eugene wrote:
> Get ready for a potentially stupid question (or at least a question I
> probably should know the answer to by now)...
This is a perfectly valid question.
I print INTN / UINTN values with:
- casting them unconditionally to INT64 / UINT64,
- printing the converted values with the matching conversion specifiers,
such as %Ld (for INT64) and %Lu or %Lx (for UINT64).
This solution requires a bit more typing, and it is a bit pessimistic
for 32-bit builds. On the positive side, it is robust / portable, and
completely valid C.
It is inspired by the standard C types intmax_t / uintmax_t. If you
write portable C code and want to print a value of some integer type,
where the spec only states "signed" or "unsigned integer type", but the
actual type is either implementation defined or unspecified, converting
the value to intmax_t / uintmax_t, and then printing it with %jd vs. %ju
/ %jx, is safe.
Regarding %p (relayed by Alexei as a recommendation from years ago),
that's a bug. %p takes a pointer to void. If we ever enable format
string checking in edk2, for example with GCC's
__attribute__((format(printf, ..., ...))), all those calls will blow up.
Thanks
Laszlo
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-26 15:31 ` Laszlo Ersek
@ 2016-09-27 12:29 ` Cohen, Eugene
2016-09-27 14:30 ` Laszlo Ersek
0 siblings, 1 reply; 16+ messages in thread
From: Cohen, Eugene @ 2016-09-27 12:29 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: edk2-devel@lists.01.org, Kinney, Michael D, Alexei Fedorov
Laszlo,
> I print INTN / UINTN values with:
> - casting them unconditionally to INT64 / UINT64,
> - printing the converted values with the matching conversion
> specifiers,
> such as %Ld (for INT64) and %Lu or %Lx (for UINT64).
>
> This solution requires a bit more typing, and it is a bit pessimistic
> for 32-bit builds. On the positive side, it is robust / portable, and
> completely valid C.
>
> It is inspired by the standard C types intmax_t / uintmax_t. If you
> write portable C code and want to print a value of some integer type,
> where the spec only states "signed" or "unsigned integer type", but
> the
> actual type is either implementation defined or unspecified,
> converting
> the value to intmax_t / uintmax_t, and then printing it with %jd vs. %ju
> / %jx, is safe.
Thanks - this makes sense. If this methodology is consistent with standard C then perhaps it's the best compromise even if it's messy to read.
>From a consistency perspective I see a lot of variation in usage - often UINTNs are printed with %x / %d (technically it should be %u but this is a common error - just compare the number of occurrences of %u in MdeModulePkg versus %d). This means that the caller is expecting that the value will never exceed 2^32-1 on 64-bit systems since we are doing 64-bit to 32-bit truncation through the cast in the VA_ARG macro. I'm concerned that this requires the developer to know the constraints on the value in all circumstances which seems dubious - after all that's why we have types in the first place, so the tools can help us do the right thing.
I'm envisioning having to create a slide in the future for UEFI training about the proper use of UINTNs and describing "If you think it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry about it" and it makes me squirm.
Eugene
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 12:29 ` Cohen, Eugene
@ 2016-09-27 14:30 ` Laszlo Ersek
2016-09-27 16:03 ` Cohen, Eugene
0 siblings, 1 reply; 16+ messages in thread
From: Laszlo Ersek @ 2016-09-27 14:30 UTC (permalink / raw)
To: Cohen, Eugene; +Cc: edk2-devel@lists.01.org, Kinney, Michael D, Alexei Fedorov
On 09/27/16 14:29, Cohen, Eugene wrote:
> Laszlo,
>
>> I print INTN / UINTN values with:
>> - casting them unconditionally to INT64 / UINT64,
>> - printing the converted values with the matching conversion
>> specifiers,
>> such as %Ld (for INT64) and %Lu or %Lx (for UINT64).
>>
>> This solution requires a bit more typing, and it is a bit pessimistic
>> for 32-bit builds. On the positive side, it is robust / portable, and
>> completely valid C.
>>
>> It is inspired by the standard C types intmax_t / uintmax_t. If you
>> write portable C code and want to print a value of some integer type,
>> where the spec only states "signed" or "unsigned integer type", but
>> the
>> actual type is either implementation defined or unspecified,
>> converting
>> the value to intmax_t / uintmax_t, and then printing it with %jd vs. %ju
>> / %jx, is safe.
>
> Thanks - this makes sense. If this methodology is consistent with
> standard C then perhaps it's the best compromise even if it's messy
> to read.
>
> From a consistency perspective I see a lot of variation in usage -
> often UINTNs are printed with %x / %d (technically it should be %u
> but this is a common error - just compare the number of occurrences
> of %u in MdeModulePkg versus %d).
Printing UINTN with %x *or* with %d are equally bugs.
For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
work most of the time).
For Ia32 / ARM builds, %x is not an actual bug, just a portability one /
code smell. And %d may or may not be an actual bug, dependent on the
value being printed.
> This means that the caller is
> expecting that the value will never exceed 2^32-1 on 64-bit systems
> since we are doing 64-bit to 32-bit truncation through the cast in
> the VA_ARG macro.
I think that the specifics why printing UINTN with %x (or %d) happens to
work on X64 / AARCH64, for a subset of the UINTN values, are not
interesting. As far as I'm concerned, even the argument *sizes* are
wrong, which might as well lead to incorrect accesses to the stack.
> I'm concerned that this requires the developer to
> know the constraints on the value in all circumstances which seems
> dubious - after all that's why we have types in the first place, so
> the tools can help us do the right thing.
The developer is first and foremost required to match the conversion
specifiers to the types of the arguments being passed. For UINTN there
is no dedicated conversion specifier, hence my recommendation for the
casting.
> I'm envisioning having to create a slide in the future for UEFI
> training about the proper use of UINTNs and describing "If you think
> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> about it" and it makes me squirm.
It makes me squirm too. I think the slide should recommend the casting
that I proposed. ;) "There is no conversion specifier dedicated to
UINTN; the portable way to print it is to cast it to UINT64, then print
it with %Lx."
Thanks
Laszlo
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 14:30 ` Laszlo Ersek
@ 2016-09-27 16:03 ` Cohen, Eugene
2016-09-27 16:31 ` Laszlo Ersek
2016-09-27 16:47 ` Andrew Fish
0 siblings, 2 replies; 16+ messages in thread
From: Cohen, Eugene @ 2016-09-27 16:03 UTC (permalink / raw)
To: Laszlo Ersek; +Cc: Kinney, Michael D, Alexei Fedorov, edk2-devel@lists.01.org
> Printing UINTN with %x *or* with %d are equally bugs.
>
> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
> work most of the time).
Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking and running]. :)
> > I'm envisioning having to create a slide in the future for UEFI
> > training about the proper use of UINTNs and describing "If you think
> > it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> > about it" and it makes me squirm.
>
> It makes me squirm too. I think the slide should recommend the
> casting
> that I proposed. ;) "There is no conversion specifier dedicated to
> UINTN; the portable way to print it is to cast it to UINT64, then print
> it with %Lx."
This is reasonable although I expect to get asked why a lot of the other code doesn't adhere to this recommendation.
Thanks,
Eugene
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 16:03 ` Cohen, Eugene
@ 2016-09-27 16:31 ` Laszlo Ersek
2016-09-27 16:47 ` Andrew Fish
1 sibling, 0 replies; 16+ messages in thread
From: Laszlo Ersek @ 2016-09-27 16:31 UTC (permalink / raw)
To: Cohen, Eugene; +Cc: Kinney, Michael D, Alexei Fedorov, edk2-devel@lists.01.org
On 09/27/16 18:03, Cohen, Eugene wrote:
>> Printing UINTN with %x *or* with %d are equally bugs.
>>
>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>> work most of the time).
>
> Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking and running]. :)
Not a bad idea, but it's not practical. I take care to use the right
casts and conversion specifiers whenever I write new code, but for
identifying existent incorrect calls, compiler support would be necessary.
I guess we could add the GCC function attribute that I mentioned earlier
to some of the PrintLib functions, and then address the resultant
warning messages. The problem is that some of the edk2-defined
conversion specifiers
- are not defined in standard (or GNU) C -- for example, %t --, which
might prevent GCC from pairing the corresponding argument with any
conversion specifier at all,
- and/or work differently from their standard (or GNU) C counterparts:
- for example %g is entirely different between edk2 and standard C
((EFI_GUID *) vs. double),
- the "L" length modifier is invalid for %x in standard C,
- etc.
If someone is into GCC or CLANG plugin development, creating an "edk2
PrintLib" function attribute could be a good task :)
>>> I'm envisioning having to create a slide in the future for UEFI
>>> training about the proper use of UINTNs and describing "If you think
>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>>> about it" and it makes me squirm.
>>
>> It makes me squirm too. I think the slide should recommend the
>> casting
>> that I proposed. ;) "There is no conversion specifier dedicated to
>> UINTN; the portable way to print it is to cast it to UINT64, then print
>> it with %Lx."
>
> This is reasonable although I expect to get asked why a lot of the other code doesn't adhere to this recommendation.
"Because people didn't realize it was a bug and it worked in practice"? :)
Thanks
Laszlo
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 16:03 ` Cohen, Eugene
2016-09-27 16:31 ` Laszlo Ersek
@ 2016-09-27 16:47 ` Andrew Fish
2016-09-27 17:14 ` Brian J. Johnson
2016-09-27 17:27 ` Kinney, Michael D
1 sibling, 2 replies; 16+ messages in thread
From: Andrew Fish @ 2016-09-27 16:47 UTC (permalink / raw)
To: Eugene Cohen
Cc: Laszlo Ersek, Mike Kinney, Alexei Fedorov,
edk2-devel@lists.01.org
> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene <eugene@hp.com> wrote:
>
>> Printing UINTN with %x *or* with %d are equally bugs.
>>
>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>> work most of the time).
>
> Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking and running]. :)
>
>>> I'm envisioning having to create a slide in the future for UEFI
>>> training about the proper use of UINTNs and describing "If you think
>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>>> about it" and it makes me squirm.
>>
>> It makes me squirm too. I think the slide should recommend the
>> casting
>> that I proposed. ;) "There is no conversion specifier dedicated to
>> UINTN; the portable way to print it is to cast it to UINT64, then print
>> it with %Lx."
>
> This is reasonable although I expect to get asked why a lot of the other code doesn't adhere to this recommendation.
>
I think this is a historical artifact. The older version of %x in the EDK (and early edk2) implied UINTN. We hit an issue with C integer math resulting in an int and that seemed to bork some toolchains. That is when things changed from UINTN to int. I guess the cleanup was practical vs. pedantic.
Thanks,
Andrew Fish
> Thanks,
>
> Eugene
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 16:47 ` Andrew Fish
@ 2016-09-27 17:14 ` Brian J. Johnson
2016-09-27 18:31 ` Laszlo Ersek
2016-09-27 20:27 ` Kinney, Michael D
2016-09-27 17:27 ` Kinney, Michael D
1 sibling, 2 replies; 16+ messages in thread
From: Brian J. Johnson @ 2016-09-27 17:14 UTC (permalink / raw)
To: Andrew Fish, Eugene Cohen
Cc: Mike Kinney, Alexei Fedorov, edk2-devel@lists.01.org,
Laszlo Ersek
On 09/27/2016 11:47 AM, Andrew Fish wrote:
>
>> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene <eugene@hp.com> wrote:
>>
>>> Printing UINTN with %x *or* with %d are equally bugs.
>>>
>>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>>> work most of the time).
>>
>> Feel free to file a Bugzilla on the extensive usage of this in
>> edk2 [ducking and running]. :)
>>
>>>> I'm envisioning having to create a slide in the future for UEFI
>>>> training about the proper use of UINTNs and describing "If you think
>>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>>>> about it" and it makes me squirm.
>>>
>>> It makes me squirm too. I think the slide should recommend the
>>> casting
>>> that I proposed. ;) "There is no conversion specifier dedicated to
>>> UINTN; the portable way to print it is to cast it to UINT64, then print
>>> it with %Lx."
>>
>> This is reasonable although I expect to get asked why a lot of the
>> other code doesn't adhere to this recommendation.
>>
>
> I think this is a historical artifact. The older version of %x in
> the EDK (and early edk2) implied UINTN. We hit an issue with C
> integer math resulting in an int and that seemed to bork some
> toolchains. That is when things changed from UINTN to int. I guess
> the cleanup was practical vs. pedantic.
Thanks for the historical context, Andrew. It's interesting to hear,
if very unfortunate.
I've written code in the past which uses a #defined value for the
UINTN format character as a way to work around this issue without
casting everything to 64 bits. Something like:
// Format string for a naturally-sized unsigned integer
#if defined (MDE_CPU_IA32)
#define UINTN_FMT "0x%08x"
#elif defined (MDE_CPU_X64)
#define UINTN_FMT "0x%016lx"
#elif ...
...
#endif
UINTN Val;
Val = Foo ();
DEBUG((DEBUG_INFO, "Value is " UINTN_FMT "\n", Val));
I guess it's a matter of opinion if that's preferable to adding casts;
in my particular situation, I had to print values with that particular
format string in a lot of places, so it was convenient to #define it
once.
>
> Thanks,
>
> Andrew Fish
>
>> Thanks,
>>
>> Eugene
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
>
--
Brian J. Johnson
--------------------------------------------------------------------
My statements are my own, are not authorized by SGI, and do not
necessarily represent SGI’s positions.
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 16:47 ` Andrew Fish
2016-09-27 17:14 ` Brian J. Johnson
@ 2016-09-27 17:27 ` Kinney, Michael D
2016-09-27 17:46 ` Andrew Fish
2016-09-27 19:28 ` Cohen, Eugene
1 sibling, 2 replies; 16+ messages in thread
From: Kinney, Michael D @ 2016-09-27 17:27 UTC (permalink / raw)
To: afish@apple.com, Eugene Cohen, Kinney, Michael D
Cc: Laszlo Ersek, Alexei Fedorov, edk2-devel@lists.01.org
Andrew,
Here is the comment in current code that explains some of the why.
case 'd':
if ((Flags & LONG_TYPE) == 0) {
//
// 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
// This assumption is made so the format string definition is compatible with the ANSI C
// Specification for formatted strings. It is recommended that the Base Types be used
// everywhere, but in this one case, compliance with ANSI C is more important, and
// provides an implementation that is compatible with that largest possible set of CPU
// architectures. This is why the type "int" is used in this one case.
//
If code uses type UINTN or INTN, then the max value that can be used
for portable sources is max value for the CPU arch with the smallest
UINTN width. For the CPU archs in UEFI/PI specs today, the smallest UINTN
width is 32-bits.
Portable sources that use type UINTN must never use values larger than
32-bits. Same for type INTN. Only use values in signed 32-bit range.
It is possible for 64-bit specific sources to use type UINTN with values
larger than 32-bits, but those sources would not be portable and would
need to be changed to UINT64 to be portable. Is this the case that are
really discussing here?
Thanks,
Mike
> -----Original Message-----
> From: afish@apple.com [mailto:afish@apple.com]
> Sent: Tuesday, September 27, 2016 9:47 AM
> To: Eugene Cohen <eugene@hp.com>
> Cc: Laszlo Ersek <lersek@redhat.com>; Kinney, Michael D <michael.d.kinney@intel.com>;
> Alexei Fedorov <Alexei.Fedorov@arm.com>; edk2-devel@lists.01.org <edk2-
> devel@ml01.01.org>
> Subject: Re: [edk2] What is the right way to print a UINTN?
>
>
> > On Sep 27, 2016, at 9:03 AM, Cohen, Eugene <eugene@hp.com> wrote:
> >
> >> Printing UINTN with %x *or* with %d are equally bugs.
> >>
> >> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
> >> work most of the time).
> >
> > Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking and
> running]. :)
> >
> >>> I'm envisioning having to create a slide in the future for UEFI
> >>> training about the proper use of UINTNs and describing "If you think
> >>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> >>> about it" and it makes me squirm.
> >>
> >> It makes me squirm too. I think the slide should recommend the
> >> casting
> >> that I proposed. ;) "There is no conversion specifier dedicated to
> >> UINTN; the portable way to print it is to cast it to UINT64, then print
> >> it with %Lx."
> >
> > This is reasonable although I expect to get asked why a lot of the other code doesn't
> adhere to this recommendation.
> >
>
> I think this is a historical artifact. The older version of %x in the EDK (and early
> edk2) implied UINTN. We hit an issue with C integer math resulting in an int and that
> seemed to bork some toolchains. That is when things changed from UINTN to int. I guess
> the cleanup was practical vs. pedantic.
>
> Thanks,
>
> Andrew Fish
>
> > Thanks,
> >
> > Eugene
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 17:27 ` Kinney, Michael D
@ 2016-09-27 17:46 ` Andrew Fish
2016-09-27 18:20 ` Kinney, Michael D
2016-09-27 19:28 ` Cohen, Eugene
1 sibling, 1 reply; 16+ messages in thread
From: Andrew Fish @ 2016-09-27 17:46 UTC (permalink / raw)
To: Mike Kinney
Cc: Eugene Cohen, Alexei Fedorov, edk2-devel@lists.01.org,
Laszlo Ersek
> On Sep 27, 2016, at 10:27 AM, Kinney, Michael D <michael.d.kinney@intel.com> wrote:
>
> Andrew,
>
> Here is the comment in current code that explains some of the why.
>
> case 'd':
> if ((Flags & LONG_TYPE) == 0) {
> //
> // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".
> // This assumption is made so the format string definition is compatible with the ANSI C
> // Specification for formatted strings. It is recommended that the Base Types be used
> // everywhere, but in this one case, compliance with ANSI C is more important, and
> // provides an implementation that is compatible with that largest possible set of CPU
> // architectures. This is why the type "int" is used in this one case.
> //
>
> If code uses type UINTN or INTN, then the max value that can be used
> for portable sources is max value for the CPU arch with the smallest
> UINTN width. For the CPU archs in UEFI/PI specs today, the smallest UINTN
> width is 32-bits.
>
> Portable sources that use type UINTN must never use values larger than
> 32-bits. Same for type INTN. Only use values in signed 32-bit range.
>
> It is possible for 64-bit specific sources to use type UINTN with values
> larger than 32-bits, but those sources would not be portable and would
> need to be changed to UINT64 to be portable. Is this the case that are
> really discussing here?
>
If you have a UINTN that can only represent 32-bits is that not a UINT32 :).
Thanks,
Andrew Fish
> Thanks,
>
> Mike
>
>
>> -----Original Message-----
>> From: afish@apple.com [mailto:afish@apple.com]
>> Sent: Tuesday, September 27, 2016 9:47 AM
>> To: Eugene Cohen <eugene@hp.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>; Kinney, Michael D <michael.d.kinney@intel.com>;
>> Alexei Fedorov <Alexei.Fedorov@arm.com>; edk2-devel@lists.01.org <edk2-
>> devel@ml01.01.org>
>> Subject: Re: [edk2] What is the right way to print a UINTN?
>>
>>
>>> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene <eugene@hp.com> wrote:
>>>
>>>> Printing UINTN with %x *or* with %d are equally bugs.
>>>>
>>>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>>>> work most of the time).
>>>
>>> Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking and
>> running]. :)
>>>
>>>>> I'm envisioning having to create a slide in the future for UEFI
>>>>> training about the proper use of UINTNs and describing "If you think
>>>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>>>>> about it" and it makes me squirm.
>>>>
>>>> It makes me squirm too. I think the slide should recommend the
>>>> casting
>>>> that I proposed. ;) "There is no conversion specifier dedicated to
>>>> UINTN; the portable way to print it is to cast it to UINT64, then print
>>>> it with %Lx."
>>>
>>> This is reasonable although I expect to get asked why a lot of the other code doesn't
>> adhere to this recommendation.
>>>
>>
>> I think this is a historical artifact. The older version of %x in the EDK (and early
>> edk2) implied UINTN. We hit an issue with C integer math resulting in an int and that
>> seemed to bork some toolchains. That is when things changed from UINTN to int. I guess
>> the cleanup was practical vs. pedantic.
>>
>> Thanks,
>>
>> Andrew Fish
>>
>>> Thanks,
>>>
>>> Eugene
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org
>>> https://lists.01.org/mailman/listinfo/edk2-devel
>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 17:46 ` Andrew Fish
@ 2016-09-27 18:20 ` Kinney, Michael D
0 siblings, 0 replies; 16+ messages in thread
From: Kinney, Michael D @ 2016-09-27 18:20 UTC (permalink / raw)
To: afish@apple.com, Kinney, Michael D
Cc: Eugene Cohen, Alexei Fedorov, edk2-devel@lists.01.org,
Laszlo Ersek
Andrew,
Yes. Using fixed with base types instead of natural width base types is clearer
and very portable.
We do use UINTN in UEFI/PI spec APIs on purpose when the range of the argument
does need vary for different CPU widths. Using UINTN in function args
and local variables also generates smaller code in most cases because UINTN
usually matches the stack and register width. So there are good reasons to
use UINTN/INTN.
I did find the commit where the use of 'int' was added to pull arguments from the
var arg list. Dated 6/3/2006.
SHA-1: 1d580c14473896b5b593a7f60a21f532008265d0
* 1) Add support for %p to print pointers
2) Fix %d,%x,%X to pull values off the vararg stack using (int) and (unsigned int)
types to resolve compatibility issues with X64
Best regards,
Mike
> -----Original Message-----
> From: afish@apple.com [mailto:afish@apple.com]
> Sent: Tuesday, September 27, 2016 10:47 AM
> To: Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: Eugene Cohen <eugene@hp.com>; Alexei Fedorov <Alexei.Fedorov@arm.com>; edk2-
> devel@lists.01.org <edk2-devel@ml01.01.org>; Laszlo Ersek <lersek@redhat.com>
> Subject: Re: [edk2] What is the right way to print a UINTN?
>
>
> > On Sep 27, 2016, at 10:27 AM, Kinney, Michael D <michael.d.kinney@intel.com> wrote:
> >
> > Andrew,
> >
> > Here is the comment in current code that explains some of the why.
> >
> > case 'd':
> > if ((Flags & LONG_TYPE) == 0) {
> > //
> > // 'd', 'u', 'x', and 'X' that are not preceded by 'l' or 'L' are assumed to
> be type "int".
> > // This assumption is made so the format string definition is compatible
> with the ANSI C
> > // Specification for formatted strings. It is recommended that the Base
> Types be used
> > // everywhere, but in this one case, compliance with ANSI C is more
> important, and
> > // provides an implementation that is compatible with that largest possible
> set of CPU
> > // architectures. This is why the type "int" is used in this one case.
> > //
> >
> > If code uses type UINTN or INTN, then the max value that can be used
> > for portable sources is max value for the CPU arch with the smallest
> > UINTN width. For the CPU archs in UEFI/PI specs today, the smallest UINTN
> > width is 32-bits.
> >
> > Portable sources that use type UINTN must never use values larger than
> > 32-bits. Same for type INTN. Only use values in signed 32-bit range.
> >
> > It is possible for 64-bit specific sources to use type UINTN with values
> > larger than 32-bits, but those sources would not be portable and would
> > need to be changed to UINT64 to be portable. Is this the case that are
> > really discussing here?
> >
>
> If you have a UINTN that can only represent 32-bits is that not a UINT32 :).
>
> Thanks,
>
> Andrew Fish
>
> > Thanks,
> >
> > Mike
> >
> >
> >> -----Original Message-----
> >> From: afish@apple.com [mailto:afish@apple.com]
> >> Sent: Tuesday, September 27, 2016 9:47 AM
> >> To: Eugene Cohen <eugene@hp.com>
> >> Cc: Laszlo Ersek <lersek@redhat.com>; Kinney, Michael D
> <michael.d.kinney@intel.com>;
> >> Alexei Fedorov <Alexei.Fedorov@arm.com>; edk2-devel@lists.01.org <edk2-
> >> devel@ml01.01.org>
> >> Subject: Re: [edk2] What is the right way to print a UINTN?
> >>
> >>
> >>> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene <eugene@hp.com> wrote:
> >>>
> >>>> Printing UINTN with %x *or* with %d are equally bugs.
> >>>>
> >>>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
> >>>> work most of the time).
> >>>
> >>> Feel free to file a Bugzilla on the extensive usage of this in edk2 [ducking and
> >> running]. :)
> >>>
> >>>>> I'm envisioning having to create a slide in the future for UEFI
> >>>>> training about the proper use of UINTNs and describing "If you think
> >>>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> >>>>> about it" and it makes me squirm.
> >>>>
> >>>> It makes me squirm too. I think the slide should recommend the
> >>>> casting
> >>>> that I proposed. ;) "There is no conversion specifier dedicated to
> >>>> UINTN; the portable way to print it is to cast it to UINT64, then print
> >>>> it with %Lx."
> >>>
> >>> This is reasonable although I expect to get asked why a lot of the other code
> doesn't
> >> adhere to this recommendation.
> >>>
> >>
> >> I think this is a historical artifact. The older version of %x in the EDK (and early
> >> edk2) implied UINTN. We hit an issue with C integer math resulting in an int and
> that
> >> seemed to bork some toolchains. That is when things changed from UINTN to int. I
> guess
> >> the cleanup was practical vs. pedantic.
> >>
> >> Thanks,
> >>
> >> Andrew Fish
> >>
> >>> Thanks,
> >>>
> >>> Eugene
> >>> _______________________________________________
> >>> edk2-devel mailing list
> >>> edk2-devel@lists.01.org
> >>> https://lists.01.org/mailman/listinfo/edk2-devel
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 17:14 ` Brian J. Johnson
@ 2016-09-27 18:31 ` Laszlo Ersek
2016-09-27 20:27 ` Kinney, Michael D
1 sibling, 0 replies; 16+ messages in thread
From: Laszlo Ersek @ 2016-09-27 18:31 UTC (permalink / raw)
To: Brian J. Johnson, Andrew Fish, Eugene Cohen
Cc: Mike Kinney, Alexei Fedorov, edk2-devel@lists.01.org
On 09/27/16 19:14, Brian J. Johnson wrote:
> On 09/27/2016 11:47 AM, Andrew Fish wrote:
>>
>>> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene <eugene@hp.com> wrote:
>>>
>>>> Printing UINTN with %x *or* with %d are equally bugs.
>>>>
>>>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
>>>> work most of the time).
>>>
>>> Feel free to file a Bugzilla on the extensive usage of this in
>>> edk2 [ducking and running]. :)
>>>
>>>>> I'm envisioning having to create a slide in the future for UEFI
>>>>> training about the proper use of UINTNs and describing "If you think
>>>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
>>>>> about it" and it makes me squirm.
>>>>
>>>> It makes me squirm too. I think the slide should recommend the
>>>> casting
>>>> that I proposed. ;) "There is no conversion specifier dedicated to
>>>> UINTN; the portable way to print it is to cast it to UINT64, then print
>>>> it with %Lx."
>>>
>>> This is reasonable although I expect to get asked why a lot of the
>>> other code doesn't adhere to this recommendation.
>>>
>>
>> I think this is a historical artifact. The older version of %x in
>> the EDK (and early edk2) implied UINTN. We hit an issue with C
>> integer math resulting in an int and that seemed to bork some
>> toolchains. That is when things changed from UINTN to int. I guess
>> the cleanup was practical vs. pedantic.
>
> Thanks for the historical context, Andrew. It's interesting to hear,
> if very unfortunate.
>
> I've written code in the past which uses a #defined value for the
> UINTN format character as a way to work around this issue without
> casting everything to 64 bits. Something like:
>
> // Format string for a naturally-sized unsigned integer
> #if defined (MDE_CPU_IA32)
> #define UINTN_FMT "0x%08x"
> #elif defined (MDE_CPU_X64)
> #define UINTN_FMT "0x%016lx"
> #elif ...
> ...
> #endif
>
> UINTN Val;
> Val = Foo ();
> DEBUG((DEBUG_INFO, "Value is " UINTN_FMT "\n", Val));
>
>
> I guess it's a matter of opinion if that's preferable to adding casts;
> in my particular situation, I had to print values with that particular
> format string in a lot of places, so it was convenient to #define it
> once.
I find this great; standard C also has macros for format specifiers, for
example PRIu64, PRId32, PRIx64, and so on.
PrintLib.h could be extended with PRIuN ("u"/"Lu"), PRIxN ("x"/"Lx"),
PRIdN ("d"/"Ld") and PRIiN ("i"/"Li"), to be defined similarly to your
code above (covering all supported CPU architectures). Then code could
use them like
DEBUG ((DEBUG_INFO, "Value is 0x%" PRIxN "\n", Val));
The field width, if necessary, can be passed in as an argument,
DEBUG ((DEBUG_INFO, "Value is 0x%0*" PRIxN "\n", 2 * sizeof Val, Val));
If this is deemed too messy, we could define further macros for the
zero-padded conversions.
Thanks,
Laszlo
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 17:27 ` Kinney, Michael D
2016-09-27 17:46 ` Andrew Fish
@ 2016-09-27 19:28 ` Cohen, Eugene
2016-09-27 20:10 ` Kinney, Michael D
1 sibling, 1 reply; 16+ messages in thread
From: Cohen, Eugene @ 2016-09-27 19:28 UTC (permalink / raw)
To: Kinney, Michael D, afish@apple.com
Cc: Laszlo Ersek, Alexei Fedorov, edk2-devel@lists.01.org
MIke,
> Portable sources that use type UINTN must never use values larger
> than
> 32-bits. Same for type INTN. Only use values in signed 32-bit range.
If the value is something like an enumeration or bitmask then I agree, but not if it's something numeric that is supposed to scale to larger numbers on 64-bit platforms like the Length field of CopyMem.
I like the proposals to use a custom format specifier (although the concatenated string with macro will take some getting used to).
Thanks,
Eugene
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 19:28 ` Cohen, Eugene
@ 2016-09-27 20:10 ` Kinney, Michael D
0 siblings, 0 replies; 16+ messages in thread
From: Kinney, Michael D @ 2016-09-27 20:10 UTC (permalink / raw)
To: Cohen, Eugene, afish@apple.com, Kinney, Michael D
Cc: Alexei Fedorov, edk2-devel@lists.01.org, Laszlo Ersek
Eugene,
I agree. There are use cases for using UINTN so values can scale to CPU arch.
Casting those specific use cases from UINTN to UINT64 when used in a print call
is likely the safest method.
There are many use case of UINTN where the value is limited to 32-bits, and
a typecast is not required.
The format specifier idea is interesting. I need to lookup the ANSI C versions
of those. Looks like they were introduced in C99.
Mike
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Cohen, Eugene
> Sent: Tuesday, September 27, 2016 12:29 PM
> To: Kinney, Michael D <michael.d.kinney@intel.com>; afish@apple.com
> Cc: Alexei Fedorov <Alexei.Fedorov@arm.com>; edk2-devel@lists.01.org <edk2-
> devel@ml01.01.org>; Laszlo Ersek <lersek@redhat.com>
> Subject: Re: [edk2] What is the right way to print a UINTN?
>
> MIke,
>
> > Portable sources that use type UINTN must never use values larger
> > than
> > 32-bits. Same for type INTN. Only use values in signed 32-bit range.
>
> If the value is something like an enumeration or bitmask then I agree, but not if it's
> something numeric that is supposed to scale to larger numbers on 64-bit platforms like
> the Length field of CopyMem.
>
> I like the proposals to use a custom format specifier (although the concatenated string
> with macro will take some getting used to).
>
> Thanks,
>
> Eugene
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: What is the right way to print a UINTN?
2016-09-27 17:14 ` Brian J. Johnson
2016-09-27 18:31 ` Laszlo Ersek
@ 2016-09-27 20:27 ` Kinney, Michael D
1 sibling, 0 replies; 16+ messages in thread
From: Kinney, Michael D @ 2016-09-27 20:27 UTC (permalink / raw)
To: Brian J. Johnson, Andrew Fish, Eugene Cohen, Kinney, Michael D
Cc: Alexei Fedorov, edk2-devel@lists.01.org, Laszlo Ersek
Hi Brian,
This is a good idea. I will have to study it some more
to figure out what the EBC versions of these macros would
map to.
Mike
> -----Original Message-----
> From: Brian J. Johnson [mailto:bjohnson@sgi.com]
> Sent: Tuesday, September 27, 2016 10:14 AM
> To: Andrew Fish <afish@apple.com>; Eugene Cohen <eugene@hp.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>; Alexei Fedorov
> <Alexei.Fedorov@arm.com>; edk2-devel@lists.01.org <edk2-devel@ml01.01.org>; Laszlo
> Ersek <lersek@redhat.com>
> Subject: Re: [edk2] What is the right way to print a UINTN?
>
> On 09/27/2016 11:47 AM, Andrew Fish wrote:
> >
> >> On Sep 27, 2016, at 9:03 AM, Cohen, Eugene <eugene@hp.com> wrote:
> >>
> >>> Printing UINTN with %x *or* with %d are equally bugs.
> >>>
> >>> For X64 / AARCH64 / IA64 builds, they are actual bugs (that happen to
> >>> work most of the time).
> >>
> >> Feel free to file a Bugzilla on the extensive usage of this in
> >> edk2 [ducking and running]. :)
> >>
> >>>> I'm envisioning having to create a slide in the future for UEFI
> >>>> training about the proper use of UINTNs and describing "If you think
> >>>> it may exceed 2^32-1 then upcast to UINT64, otherwise don't worry
> >>>> about it" and it makes me squirm.
> >>>
> >>> It makes me squirm too. I think the slide should recommend the
> >>> casting
> >>> that I proposed. ;) "There is no conversion specifier dedicated to
> >>> UINTN; the portable way to print it is to cast it to UINT64, then print
> >>> it with %Lx."
> >>
> >> This is reasonable although I expect to get asked why a lot of the
> >> other code doesn't adhere to this recommendation.
> >>
> >
> > I think this is a historical artifact. The older version of %x in
> > the EDK (and early edk2) implied UINTN. We hit an issue with C
> > integer math resulting in an int and that seemed to bork some
> > toolchains. That is when things changed from UINTN to int. I guess
> > the cleanup was practical vs. pedantic.
>
> Thanks for the historical context, Andrew. It's interesting to hear,
> if very unfortunate.
>
> I've written code in the past which uses a #defined value for the
> UINTN format character as a way to work around this issue without
> casting everything to 64 bits. Something like:
>
> // Format string for a naturally-sized unsigned integer
> #if defined (MDE_CPU_IA32)
> #define UINTN_FMT "0x%08x"
> #elif defined (MDE_CPU_X64)
> #define UINTN_FMT "0x%016lx"
> #elif ...
> ...
> #endif
>
> UINTN Val;
> Val = Foo ();
> DEBUG((DEBUG_INFO, "Value is " UINTN_FMT "\n", Val));
>
>
> I guess it's a matter of opinion if that's preferable to adding casts;
> in my particular situation, I had to print values with that particular
> format string in a lot of places, so it was convenient to #define it
> once.
>
> >
> > Thanks,
> >
> > Andrew Fish
> >
> >> Thanks,
> >>
> >> Eugene
> >> _______________________________________________
> >> edk2-devel mailing list
> >> edk2-devel@lists.01.org
> >> https://lists.01.org/mailman/listinfo/edk2-devel
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel
> >
>
>
> --
>
> Brian J. Johnson
>
> --------------------------------------------------------------------
>
> My statements are my own, are not authorized by SGI, and do not
> necessarily represent SGI's positions.
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2016-09-27 20:27 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-09-26 13:46 What is the right way to print a UINTN? Cohen, Eugene
2016-09-26 14:39 ` Alexei Fedorov
2016-09-26 15:31 ` Laszlo Ersek
2016-09-27 12:29 ` Cohen, Eugene
2016-09-27 14:30 ` Laszlo Ersek
2016-09-27 16:03 ` Cohen, Eugene
2016-09-27 16:31 ` Laszlo Ersek
2016-09-27 16:47 ` Andrew Fish
2016-09-27 17:14 ` Brian J. Johnson
2016-09-27 18:31 ` Laszlo Ersek
2016-09-27 20:27 ` Kinney, Michael D
2016-09-27 17:27 ` Kinney, Michael D
2016-09-27 17:46 ` Andrew Fish
2016-09-27 18:20 ` Kinney, Michael D
2016-09-27 19:28 ` Cohen, Eugene
2016-09-27 20:10 ` Kinney, Michael D
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox