# $Id$ # Captive project doc Calling Types page Perl template. # Copyright (C) 2003-2005 Jan Kratochvil # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; exactly version 2 of June 1991 is required # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA package project::captive::doc::CallType; require 5.6.0; # at least 'use warnings;' but we need some 5.6.0+ modules anyway our $VERSION=do { my @r=(q$Revision$=~/\d+/g); sprintf "%d.".("%03d"x$#r),@r; }; our $CVS_ID=q$Id$; use strict; use warnings; use My::Web; sub handler { BEGIN { Wuse 'project::captive::doc::Macros'; } project::captive::doc::Macros->init( "title"=>'Captive NTFS Developer Documentation: API Calling Conventions', "rel_prev"=>'APITypes.pm', "rel_next"=>'TODO.pm', ); print <<"HERE";

API Function Calling Conventions

Standard UNIX code compiled by GCC (GNU C Compiler) running on host $gnulinux always uses @{[ a_href 'CallType.pm#calltype_cdecl','cdecl' ]} ABI (Application Binary Interface) calling convention. This calling convention is also the default declaration type of UNIX functions.

W32 uses three different calling conventions in its ABI. They are all described in the Microsoft documentation. There is always necessary to have the proper function declaration (prototype) in the caller scope to prevent all sorts of unexpected crashes.

Unfortunately some non-matching combinations of calling conventions result in hard to debug bugs: the caller gets back an unexpected stack pointer from the callee and upon return it will restore registers from the wrong stack pointer place. Since the caller will finally reclaim its stack frame from its (uncorrupted) EBP stack frame pointer the caller will return to the caller of the caller correctly. Just the registers remain corrupted causing crashes of completely unrelated code executed far, far away...

EDI, ESI and EBX registers are always saved on the stack. They are stored on the stack in this particular order from bottom to top addresses (using the push EBX, push ESI, push EDI sequence). Fortunately $gnulinux GCC has the same register saving behaviour. If some register corruption occurs the calling type presented between the caller and callee should be checked.

W32 Calling Convention "cdecl"

The only calling convention in the UNIX world. The default one for all the compilers. All the arguments are passed on the stack, no arguments are cleaned by the callee. Possible inconsistencies in the number of function arguments with the function prototype used by the caller is harmless. Variable arguments lists can be passed by this convention.

@{[ doc_img 'fig/calltype_cdecl.fig', 'W32 Calling Convention cdecl Scheme' ]}
Calling Convention cdecl Characteristics
Arguments freed by caller
Arguments on the stack #0 ... #(n-1)
Arguments in the registers none
GCC attribute __attribute__((__cdecl__)) (default)

W32 Calling Convention "stdcall"

@{[ doc_img 'fig/calltype_stdcall.fig', 'W32 Calling Convention stdcall Scheme' ]}

Convention never used in the UNIX world. It needs to be specified for W32 compilers. All the arguments are passed on the stack, all the arguments are cleaned by the callee. Possible inconsistencies in the number of function arguments with the function prototype used by the caller will result in fatal crash. Variable arguments lists cannot be passed by this convention – use @{[ a_href 'CallType.pm#calltype_cdecl','cdecl' ]} instead.

Calling Convention stdcall Characteristics
Arguments freed by callee
Arguments on the stack #0 ... #(n-1)
Arguments in the registers none
GCC attribute __attribute__((__stdcall__))

W32 Calling Convention "fastcall"

Convention never used in the UNIX world. It needs to be specified for W32 compilers. Convention used in the W32 world for its low calling overhead. All but the first two arguments are passed on the stack, such arguments are cleaned by the callee. First two arguments are passed in the registers ECX and EDX respectively. Possible inconsistencies in the number of function arguments with the function prototype used by the caller will result in fatal crash. Variable arguments lists cannot be passed by this convention – use @{[ a_href 'CallType.pm#calltype_cdecl','cdecl' ]} instead.

GCC (GNU C Compiler) native support for this calling convention is pretty fresh and it is currently present only in the recent CVS versions since 21st December of 2002 which should get released as GCC version 3.4. This project solved the unsupported calling convention by declaration of arguments passed in registers by __attribute__((__regparm__(3))). W32 passes the arguments in registers in the order ECX, EDX but GCC passes them in registers EAX, EDX, ECX. This incompatibility is compensated at C source level in the @{[ a_href '#functype','relaying code' ]} generated by captivesym relay generator.

@{[ doc_img 'fig/calltype_fastcall.fig', 'W32 Calling Convention fastcall Scheme' ]}
Calling Convention fastcall Characteristics
Arguments freed by callee
Arguments on the stack #2 ... #(n-1)
Arguments in the registers ECX=#0, EDX=#1
GCC ≥3.4 attribute __attribute__((__fastcall__))
GCC <3.4 attr. emulation__attribute__((__stdcall__))
__attribute__((__regparm__(3) /* EAX,EDX,ECX */))
HERE exit; } 1;