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>
# 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()
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";
=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