+respected proper function calling types cdecl/stdcall/fastcall
authorshort <>
Sat, 2 Nov 2002 02:42:16 +0000 (02:42 +0000)
committershort <>
Sat, 2 Nov 2002 02:42:16 +0000 (02:42 +0000)
.captivesym file $value field dropped (forced eq $symbol now)

src/libcaptive/ke/captivesym.pl

index 2a3a68e..1e21cdc 100755 (executable)
@@ -24,30 +24,52 @@ use strict;
 use warnings;
 
 
+my %def;
+map({ open DEF,"<$_" or die "open(\"$_\"): $!"; } shift());
+while (<DEF>) {
+       s/;.*//s;
+       next if /^\s*$/s;
+       my($atsign,$symbol,$args,$isdata)=(/^\s*(\@)?(\S+?)(?:\@(\d+))?(\s+DATA)?\s*$/s);
+       die "Invalid line" if !defined $symbol;
+       #          popped args          doc  ntoskrnl.def
+       # cdecl    no     stack         _f   f
+       # stdcall  yes    stack         _f@4 f@4
+       # fastcall yes    ecx,edx,stack @f@4 @f@4
+       next if $isdata;
+       die "\@funcname without \@4 suffix not recognized" if $atsign && !defined $args;
+       die "Invalid \@$args number" if defined $args && ($args<0 || ($args%4));
+       die "Duplicate symbol: $symbol" if exists $def{$symbol};
+       $def{$symbol}={
+                       "type"=>(!defined $args ? "cdecl" : (!$atsign ? "stdcall" : "fastcall")),
+                       (!defined $args ? () : ("args4"=>$args/4)),
+                       };
+       }
+close DEF or warn "close(DEF): $!";
+
 # read source
-my %module;    # $module{'module'}{'symbol'}='value'
-my %symbol;    # $symbol{'symbol'}='value'
+my %module;    # $module{'module'}{'symbol'}=1/""
+my %symbol;    # $symbol{'symbol'}=1/""
 while (<>) {
        chomp;
        next if /^\s*$/;        # empty
        next if /^\s*#.*/;      # comment
-       my($module,$symbol,$value)=(/^\s*(\S+)\s+(\S+)(?:\s+([\S^"<>]+))?\s*$/);
+       my($module,$symbol,$isundef)=(/^\s*(\S+)\s+(\S+)(\s+undef)?\s*$/);
        die "Invalid line" if !defined $symbol;
-       $value=$symbol if !defined $value;
-       $value=undef() if $value eq "undef";
        die "Symbol already exists: $symbol" if exists $symbol{$symbol};
-       $module{$module}{$symbol}=$value;
-       $symbol{$symbol}=$value;
+       delete $def{$symbol} if $isundef;
+       die "Symbol not in ntoskrnl.def file: $symbol" if !$isundef && !$def{$symbol};
+       $module{$module}{$symbol}=!$isundef;
+       $symbol{$symbol}=!$isundef;
        }
 
 # file header
 print <<"HERE";
-/* File generated automatically by captivesym.pl from @ARGV */
+/* File generated automatically by captivesym.pl from "$ARGV" */
 /* DO NOT EDIT! */
 
 #include "config.h"
 
-#include "captive/ldr.h"       /* for captive_ModuleList_add_builtin() */
+#include "captive/ldr_exports.h"       /* for captive_ModuleList_add_builtin() */
 #include <glib/gtypes.h>
 #include <glib/gmessages.h>
 #include <glib/gmacros.h>
@@ -57,14 +79,34 @@ HERE
 
 # undefined symbol stubs
 my $symbols_undef=0;
-for my $symbol (sort grep({ !defined $symbol{$_} } keys(%symbol))) {
-       print <<"HERE";
-static void captive_sym_undef_$symbol(void)
+for my $symbol (sort keys(%symbol)) {
+       my $def=$def{$symbol};
+       if (!$def) {
+               print <<"HERE";
+static void ${symbol}_undef(void)
 {
        g_error("%s: Function '$symbol' NOT IMPLEMENTED",G_STRLOC);
 }
 HERE
-       $symbols_undef++;
+               $symbols_undef++;
+               }
+       elsif ("cdecl" eq $def->{"type"}) {
+               print "void/* ==unknown */ ${symbol}(void/* ==unknown */);\n",
+                               "#define ${symbol}_".$def->{"type"}." ${symbol}\n";
+               }
+       else {
+               my @args_out=map("arg$_",0..($def->{"args4"}-1));
+               my @args_in=($def->{"type"} ne "fastcall" ? @args_out
+                               : ("stub_eax","arg1","arg0",@args_out[2..$#args_out]));
+               print "guint32 ${symbol}(".(join(",",map("guint32 $_",@args_out)) || "void").");\n",
+                               "static guint32 "
+                                                               ."__attribute__((__".(map(($_ ne "fastcall" ? $_ : "stdcall"),$def->{"type"}))[0]."__)) "
+                                                               .($def->{"type"} ne "fastcall" ? "" : "__attribute__((__regparm__(3))) ")
+                                                               ."${symbol}_".$def->{"type"}."(".(join(",",map("guint32 $_",@args_in)) || "void").")\n",
+                               "{\n",
+                               "\treturn ${symbol}(".join(",",@args_out).");\n",
+                               "}\n";
+               }
        }
 
 # export function captive_kernel_exports()
@@ -75,13 +117,15 @@ gboolean captive_kernel_exports(void)
 gboolean errbool;
 
 HERE
-while (my($module,$moduleref)=each(%module)) {
+for my $module (sort keys(%module)) {
+       my $moduleref=$module{$module};
        print <<"HERE";
        errbool=captive_ModuleList_add_builtin("$module",
 HERE
-       while (my($symbol,$value)=each(%$moduleref)) {
-               print "\t\t\t\"$symbol\",&",
-                               (defined $value ? $value : "captive_sym_undef_$symbol"),
+       for my $symbol (sort keys(%$moduleref)) {
+               my $value=${$moduleref}{$symbol};
+               print "\t\t\t\"$symbol\",&${symbol}_",
+                               ($def{$symbol}{"type"} || "undef"),
                                ",\n";
                }
        print <<"HERE";
@@ -110,20 +154,42 @@ captivesym.pl - Generate source files based on .captivesym symbol file
 
 =head1 SYNOPSIS
 
-./captivesym.pl exports.captivesym E<gt>exports.c
+./captivesym.pl path/to/ntoskrnl/ntoskrnl.def exports.captivesym E<gt>exports.c
 
 =head1 DESCRIPTION
 
-Source lines consist of lines with whitespace-separated
-(B<module>,B<symbol>,[B<value>]) items.
+Source lines of I<.captivesym> file consist of lines with whitespace-separated
+(B<module>,B<symbol>,[undef]) items.
+
+=over
+
+=item undef
+
+Optional "undef" specifies invocation of a generated stub function displaying
+C<g_error()> message.
+
+=back
+
+=begin comment
+
+       choose one:
+               podchecker: *** WARNING: node 'http:$_' contains non-escaped | or /
+               pod2html: cannot resolve L.lt.http:$_.gt.
+
+=end comment
+
+Source file I<ntoskrnl.def> is required to have on of three item types
+described at
+L<http://msdn.microsoft.com/library/en-us/vclang/html/_core_argument_passing_and_naming_conventions.asp>
+(B<argslength> must be dividable by B<4>):
 
 =over
 
-=item value
+=item cdecl: functionname
+
+=item stdcall: functionname@argslength
 
-Optional B<value> field defaults to B<symbol> value.
-B<value> can be defined as "C<undef>" - such reference is passed to stub
-function displaying C<g_error()> message.
+=item fastcall: @functionname@argslength
 
 =back