PATCH: Fix 2 PPC/SYSV varargs problems
Franz Sirl
Franz.Sirl-kernel at lauterbach.com
Wed May 12 20:21:33 EST 1999
At 08:48 12.05.99 , Richard Henderson wrote:
>On Wed, May 12, 1999 at 12:19:53AM -0600, Jeffrey A Law wrote:
> > Has this problem been fixed? I see patch from Richard which looks like it
> > is related:
>
>No, this is a different, though related, problem. I need to sit
>down with the ABI to properly evaluate the patch. PPC SVR4 varargs
>seems needlessly complex.
To me it looked more like some 95%-finished stuff with untested corner cases.
>Franz, could you point me at the test cases for this?
Oops, sure. I meant them to attach to my last mail, which contained my new
patch fixing both problems below.
Thanks again for your expand_builtin_saveregs() patch, it makes life a lot
easier on PPC :-).
Franz.
-----< testcase1
/* this testcase is a modified testcase from execute/980608-1.c.
It additionally tests the handling of float args. The varargs
handling on SYSV ABI contained a bug where using more than 8 float
args before all GP regs were consumed caused a wrong stack/register
layout to be passed by the caller. The overflowed (not fitting in FP
registers) float args virtually consumed args fitting in GP regs (counted
by cum->words).
This was uncovered in real world by gnuplot.
*/
#include <stdarg.h>
static int test=23;
void f1(int a1,int a2,int a3,int a4,int a5, int a6,int a7,int a8,int a9,
int a10)
{
test = a9;
return;
}
inline void debug(const char *fp,const char *msg,...)
{
int local_var[10] = {10,};
va_list ap;
double df;
local_var[0] += test;
if (*fp != '1')
abort();
if (*msg != '2')
abort();
f1(1,2,3,4,5,6,7,8,9,local_var[0]);
va_start( ap, msg );
df = va_arg(ap,double);
if (df <1.09 || df >1.11)
abort();
df = va_arg(ap,double);
if (df <1.19 || df >1.21)
abort();
df = va_arg(ap,double);
if (df <1.29 || df >1.31)
abort();
df = va_arg(ap,double);
if (df <1.39 || df >1.41)
abort();
df = va_arg(ap,double);
if (df <1.49 || df >1.51)
abort();
if ( *va_arg(ap,char*) != '3')
abort();
if ( *va_arg(ap,char*) != '4')
abort();
if ( *va_arg(ap,char*) != '5')
abort();
df = va_arg(ap,double);
if (df <1.59 || df >1.61)
abort();
df = va_arg(ap,double);
if (df <1.69 || df >1.71)
abort();
df = va_arg(ap,double);
if (df <1.79 || df >1.81)
abort();
df = va_arg(ap,double);
if (df <1.89 || df >1.91)
abort();
if ( va_arg(ap,int) != 101)
abort();
if ( va_arg(ap,int) != 102)
abort();
if ( va_arg(ap,int) != 103)
abort();
if ( va_arg(ap,int) != 104)
abort();
if ( *va_arg(ap,char*) != '6')
abort();
if ( va_arg(ap,int) != 105)
abort();
if ( va_arg(ap,int) != 106)
abort();
if ( va_arg(ap,int) != 107)
abort();
if ( va_arg(ap,int) != 108)
abort();
if ( va_arg(ap,int) != 109)
abort();
if ( va_arg(ap,int) != 110)
abort();
va_end( ap );
}
int main(void)
{
debug("1 filepointer", "2 format", 1.1,1.2,1.3,1.4,1.5, "3","4","5",
1.6,1.7,1.8,1.9, 101,102,103,104, "6", 105,106,107,108,109,110);
exit(0);
}
-----< testcase1
-----< testcase2
/* Yet another bug in PPC/SYSV ABI varargs handling.
If the float args overflowed from FP regs into stack space before the
varargs started, the calculation of the overflow_area pointer in va_list
was buggy.
Not uncovered in real world (yet?), constructed by staring at the varargs
code.
*/
#include <stdarg.h>
inline void debug2(const char *fp,
double d1,double d2,double d3,double d4,
double d5,double d6,double d7,double d8,double d9,
const char *msg,...)
{
va_list ap;
double df;
if (*fp != '1')
abort();
if (*msg != '2')
abort();
va_start( ap, msg );
df = va_arg(ap,double);
if (df <1.09 || df >1.11)
abort();
df = va_arg(ap,double);
if (df <1.19 || df >1.21)
abort();
df = va_arg(ap,double);
if (df <1.29 || df >1.31)
abort();
df = va_arg(ap,double);
if (df <1.39 || df >1.41)
abort();
df = va_arg(ap,double);
if (df <1.49 || df >1.51)
abort();
if ( *va_arg(ap,char*) != '3')
abort();
if ( *va_arg(ap,char*) != '4')
abort();
if ( *va_arg(ap,char*) != '5')
abort();
df = va_arg(ap,double);
if (df <1.59 || df >1.61)
abort();
df = va_arg(ap,double);
if (df <1.69 || df >1.71)
abort();
df = va_arg(ap,double);
if (df <1.79 || df >1.81)
abort();
df = va_arg(ap,double);
if (df <1.89 || df >1.91)
abort();
if ( va_arg(ap,int) != 101)
abort();
if ( va_arg(ap,int) != 102)
abort();
if ( va_arg(ap,int) != 103)
abort();
if ( va_arg(ap,int) != 104)
abort();
if ( *va_arg(ap,char*) != '6')
abort();
if ( va_arg(ap,int) != 105)
abort();
if ( va_arg(ap,int) != 106)
abort();
if ( va_arg(ap,int) != 107)
abort();
if ( va_arg(ap,int) != 108)
abort();
if ( va_arg(ap,int) != 109)
abort();
df = va_arg(ap,double);
if (df <1.99 || df >2.01)
abort();
if ( va_arg(ap,int) != 110)
abort();
va_end( ap );
}
int main(void)
{
debug2("1 filepointer", 20.1,20.2,20.3,20.4,20.5,20.6,20.7,20.8,20.9,
"2 format", 1.1,1.2,1.3,1.4,1.5, "3","4","5", 1.6,1.7,1.8,1.9,
101,102,103,104, "6", 105,106,107,108,109, 2.0, 110);
exit(0);
}
-----< testcase2
[[ This message was sent via the linuxppc-dev mailing list. Replies are ]]
[[ not forced back to the list, so be sure to Cc linuxppc-dev if your ]]
[[ reply is of general interest. Please check http://lists.linuxppc.org/ ]]
[[ and http://www.linuxppc.org/ for useful information before posting. ]]
More information about the Linuxppc-dev
mailing list