Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Apr 2004 08:11:06 -0700
From:      "David O'Brien" <obrien@freebsd.org>
To:        freebsd-amd64@freebsd.org
Subject:   Re: va_list q
Message-ID:  <20040422151106.GC78422@dragon.nuxi.com>
In-Reply-To: <200404212258.01563.peter@wemm.org>
References:  <20040422050128.GQ34647@lucky.net> <200404212258.01563.peter@wemm.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Apr 21, 2004 at 10:58:01PM -0700, Peter Wemm wrote:
> > int
> > vslprintf(buf, buflen, fmt, args)
> > [...]
> > #ifndef __powerpc__
> > >            n = vslprintf(buf, buflen + 1, f, va_arg(args,
> > > va_list));
> > #else
> >             /* On the powerpc, a va_list is an array of 1 structure
> > */ n = vslprintf(buf, buflen + 1, f, va_arg(args, void *)); #endif
...
> amd64 needs to use the same code that is in the #ifdef __powerpc__.  Its 
> what we use in src/usr.sbin/pppd FWIW.
...
> As an aside, this breaks code that assums it can copy va_lists by 
> assignment.  On powerpc and amd64, you *must* use va_copy(), or you 
> simply copy the pointer, not the actual argument passing state.

If we step back a little, the code breaks because it is not ISO-C
compliant.

One must use va_copy() just like one needs to use strcpy() to get a
unique copy of a C string.  There is zero need for the
"#ifdef __powerpc__" -- that code is ISO-C compliant and should work on
all platforms.

1. Adhere to ISO C specification for stdargs:

    Do not copy ap directly:
    void foo (va_list ap) {
        va_list tap = ap;
        /* use tap */
    }

    Correct usage:
    #include <stdargs.h>
    void foo (va_list ap) {
        va_list tap;
        va_copy (tap, ap);
        /* use tap */
    }

    GCCs ap is a pointer for AMD64.  &ap does not do what you may expect.

    REVIEW ISO C99 STANDARD, SECTION 7.15.

2. Correct Prototypes when using stdargs

    By convention, GCC stdargs and varargs on AMD64 use the %al register
    to indicate the number of floating-point arguments.  The entry point
    of a function using stdargs or varargs, expects the
    %al register to be initialized properly. 
    If the function prototype used by caller doesn't include the (...),
    gcc won't initialize %al as part of the call.  And a crash and/or
    strange behavior will occur after the call.

-- 
-- David  (obrien@FreeBSD.org)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040422151106.GC78422>