avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fwd: [avr-libc-dev] Problem with unsigned long long printf()


From: Theodore A. Roth
Subject: Re: Fwd: [avr-libc-dev] Problem with unsigned long long printf()
Date: Fri, 17 Sep 2004 14:18:31 -0700 (PDT)

On Fri, 17 Sep 2004, Bernhard Walle wrote:

> Hello,
>
> did you read this on the list? Is it a bug or not?
>
>
> Regards,
> Bernhard
>
> ----- Forwarded message from Bernhard Walle <address@hidden> -----
>
> > Date: Tue, 24 Aug 2004 17:16:10 +0200
> > From: Bernhard Walle <address@hidden>
> > To: address@hidden
> > Subject: [avr-libc-dev] Problem with unsigned long long printf()
> > Mail-Followup-To: address@hidden
> > User-Agent: Mutt/1.5.6i
> >
> > Hello,
> >
> > following code:
> >
> >     unsigned long long x = 0x1;
> >     printf("%x|%x|%x|%x\n",
> >                 *((unsigned int*)(&x) + 0),
> >                 *((unsigned int*)(&x) + 1),
> >                 *((unsigned int*)(&x) + 2),
> >                 *((unsigned int*)(&x) + 3)
> >     );
> >     printf("X = %llu \n", x);
> >
> > The output is:
> >
> >     1|0|0|0
> >     X = 1543650816
> >
> > While the first proves that the assignment is correct, the second
> > output is wrong. Does anybody know the reason? Bug?
> >
> > I'm using avr-libc 1.0.4.

There seems to be a few things going on here.

First, avr-libc currently does not handle the '%llu', '%lld', etc.
specifiers. This was probably by design so as not to bloat the vfprintf
function any more than is already is.

I modified your test case to look like this:

  void
  test_llu (void)
  {
    uint8_t buf[sizeof (uint64_t)];
    uint64_t x = 0x1;
    int i;

    memcpy (buf, &x, sizeof (uint64_t));

    for (i=0; i < sizeof (uint64_t); i++)
        printf ("| %x ", buf[i]);
    printf ("|\n");

    printf ("X = %lu \n", (uint32_t)x);
    printf ("X = %llu \n", x);
  }

Then I dig into vfprintf.c to try adding support for '%llu' and friends.
See attached patch for my hack. I then got this output:

  | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
  X = 1
  X = 73091152686874624

So I dug a little deeper with the debugger and got this (this output is
more for Joerg than anyone else):

(gdb) b vfprintf.c:412
Breakpoint 3 at 0x460e: file ../../../../libc/stdio/vfprintf.c, line
412.
(gdb) c
Continuing.

Breakpoint 3, vfprintf (stream=0x8009a2, fmt=0x80014b " \n",
ap=0x8004ac)
    at ../../../../libc/stdio/vfprintf.c:412
(gdb) p a
$2 = {
  c = 0x1,
  u8 = 0x1,
  i8 = 0x1,
  l = 0x1,
  ll = 0x3100000000000001,
  ul = 0x1,
  ull = 0x3100000000000001,
  pc = 0x800001 ""
}
(gdb) c
Continuing.

Breakpoint 3, vfprintf (stream=0x8009a2, fmt=0x800156 " \n",
ap=0x8004a6)
    at ../../../../libc/stdio/vfprintf.c:412
(gdb) p a
$3 = {
  c = 0x0,
  u8 = 0x0,
  i8 = 0x0,
  l = 0x66200000,
  ll = 0x103aa0466200000,
  ul = 0x66200000,
  ull = 0x103aa0466200000,
  pc = 0x800000 ""
}

To me, this looks suspiciously like gcc is not handling the

  a.ull = va_arg (ap, unsigned long long);

call correctly when the type is 64 bits. when passing a 64 bit variable
by value, gcc pushes the 8 bytes onto the stack instead of passing via 8
registers. If my analysis is correct, then there's a bug in gcc. I would
need to dig into this more to be certain, but I don't have any more time
to allocate to this at the moment.

Joerg, what's your take on this since you are the resident printf()
expert?

---
Ted Roth
PGP Key ID: 0x18F846E9
Jabber ID: address@hidden

Attachment: avr-libc-llu-hack.diff
Description: Text document


reply via email to

[Prev in Thread] Current Thread [Next in Thread]