Reputation: 153
When compiling fortran code into object files: how does the compiler determine the symbol names?
when I use the intrinsic function "getarg" the compiler converts it into a symbol called "_getarg@12"
I looked in the external libraries and found that the symbol name inside is called "_getarg@16" what is the significance of the "@[number]" at the end of "getarg" ?
Upvotes: 3
Views: 631
Reputation: 60008
This is totally implementation dependent. You did not say, which compiler do you use. The (nonstandard) intrinsic can exist in more versions for different integer or character kinds. There can also be more versions of the runtime libraries for more computer architectures (e.g. 32 bit and 64 bit).
Upvotes: 2
Reputation: 74375
_name@length
is highly Windows-specific name mangling applied to the name of routines that obey the stdcall
(or __stdcall
by the name of the keyword used in C) calling convention, a variant of the Pascal calling convention. This is the calling convention used by all Win32 API functions and if you look at the export tables of DLLs like KERNEL32.DLL
and USER32.DLL
you'd see that all symbols are named like this.
The _...@length
decoration gives the number of bytes occupied by the routine arguments. This is necessary since in the stdcall
calling conventions it is the callee who cleans up the arguments from the stack and not the caller as is the case with the C calling convention. When the compiler generates a call to func
with two 4-byte arguments, it puts a reference to _func@8
in the object code. If the real func
happens to have different number or size of arguments, its decorated name would be something different, e.g. _func@12
and hence a link error would occur. This is very useful with dynamic libraries (DLLs). Imagine that a DLL was replaced with another version where func
takes one additional argument. If it wasn't for the name mangling (the technical term for prepending _
and adding @length
to the symbol name), the program would still call into func
with the wrong arguments and then func
would increment the stack pointer with more bytes than was the size of the passed argument list, thus breaking the caller. With name mangling in place the loader would not launch the executable at all since it would not be able to resolve the reference to _func@8
.
In your case it looks like the external library is not really intended to be used with this compiler or you are missing some pragma or compiler option. The getarg
intrinsic takes two arguments - one integer and one assumed-sized character array (string). Some compilers pass the character array size as an additional argument. With 32-bit code this would result in 2 pointers and 1 integer being passed, totalling in 12 bytes of arguments, hence the _getarg@12
. The _getarg@16
could be, for example, 64-bit routine with strings being passed by some kind of descriptor.
As IanH reminded me in his comment, another reason for this naming discrepancy could be that you are calling getarg
with fewer arguments than expected. Fortran has this peculiar feature of "prototypeless" routine calls - Fortran compilers can generate calls to routines without actually knowing their signature, unlike in C/C++ where an explicit signature has to be supplied in the form of a function prototype. This is possible since in Fortran all arguments are passed by reference and pointers are always the same size, no matter the actual type they point to. In this particular case the stdcall
name mangling plays the role of a very crude argument checking mechanism. If it wasn't for the mangling (e.g. on Linux with GNU Fortran where such decorations are not employed or if the default calling convention was cdecl
) one could call a routine with different number of arguments than expected and the linker would happily link the object code into an executable that would then most likely crash at run time.
Upvotes: 4