Variable argument call does not work on 64-bit gfortran

Bob Deen Bob.Deen@jpl.nasa.gov
Mon May 31 17:59:00 GMT 2010


Hello to all...

I have a very large legacy Fortran system that is riddled with calls to 
variadic (stdarg) C routines.  I know this is not a good idea, is not 
supported, is platform/compiler specific, etc., and if I were to design 
the interface now I would change it.  However, this system consists of 
200,000+ lines of Fortran code, with over 15,000 calls to these kinds of 
routines, so changing it would be problematic, to say the least!  I'm 
stuck with having to deal with it.

I am also very well aware of all the pitfalls involved in calling C from 
Fortran, including finding character string lengths, name mangling, pass 
by reference, array ordering, and all that.  Those are all solvable. 
The system is already set up to handle this, with 10 different methods 
currently implemented going all the way back to VAX/VMS (it's all 
centralized; I can expound on it if you want but I don't think it's 
relevant here).

Bottom line is, I'm perfectly happy with a compiler/OS specific solution 
here.

With the prologue out of the way...

The problem boils down to a Fortran routine calling a C stdarg one.  If 
I can just get to the C, I can handle all the argument passing issues.

The following is the test case:

% cat yyy.f
       program main
       call xxx(5)
       stop
       end
% cat xxx.c
#include <stdio.h>
#include <stdarg.h>

void xxx_(int *v1, ...)
//void xxx_(int *v1)
{
printf("v1=%d\n",*v1);
}

% gfortran yyy.f xxx.c
% ./a.out
Segmentation fault
%

This fails on my current target platform (gfortran 4.1.3, Red Hat 
Enterprise 5.5, 64-bit architecture).  It works on all other platforms 
I've tried, including the exact same system in 32-bit mode:

% gfortran -m32 yyy.f xxx.c
% ./a.out
v1=5
%

and on other identically-configured 32-bit machines.  It also works if 
you swap out the xxx_() declarations (to simply eliminate the "..."). 
It fails immediately, in the C function prologue; it appears to 
calculate a jump point incorrectly which then fails (sometimes with 
illegal instruction, sometimes with seg fault).  It does not make it as 
far as the actual C code, which limits my ability to work around the 
problem.

After some research (including looking at the assembler code), it 
appears that the x86_64 ABI is different for stdargs and non-stdargs 
cases.  And it seems like the gfortran compiler is using the non-stdargs 
ABI.

This is right and proper, for the standard use of Fortran.  But I'm 
hoping there's some switch I can flip that will tell the compiler to 
generate stdarg-compatible ABI calls (or alternatively, some way to 
convince C to accept the non-stdarg ABI in the stdarg macros).  Note 
that we use no Fortran libraries other than intrinsics that we do not 
build ourselves, so a global change of ABI would be fine (assuming 
intrinsics still worked).

I'm also okay with moving to gfortran 4.4 if that would help.

Platform particulars (host name deleted for security reasons):

% uname -a
Linux xxx 2.6.18-194.3.1.el5 #1 SMP Sun May 2 04:17:42 EDT 2010 x86_64 
x86_64 x86_64 GNU/Linux
% gfortran --version
GNU Fortran (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2007 Free Software Foundation, Inc.

GNU Fortran comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of GNU Fortran
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING

% gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.


Thanks...

-Bob

Bob Deen  @  NASA-JPL Multimission Image Processing Lab
Bob.Deen@jpl.nasa.gov



More information about the Fortran mailing list