1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
|
#!/usr/bin/perl
#
# For Microsoft CL this is implemented as inline assembler. So that
# even though this script can generate even Win32 code, we'll be
# using it primarily to generate Win64 modules. Both IA-64 and AMD64
# are supported...
# pull APPLINK_MAX value from applink.c...
$applink_c=$0;
$applink_c=~s|[^/\\]+$||g;
$applink_c.="applink.c";
open(INPUT,$applink_c) || die "can't open $applink_c: $!";
@max=grep {/APPLINK_MAX\s+(\d+)/} <INPUT>;
close(INPUT);
($#max==0) or die "can't find APPLINK_MAX in $applink_c";
$max[0]=~/APPLINK_MAX\s+(\d+)/;
$N=$1; # number of entries in OPENSSL_UplinkTable not including
# OPENSSL_UplinkTable[0], which contains this value...
# Idea is to fill the OPENSSL_UplinkTable with pointers to stubs
# which invoke 'void OPENSSL_Uplink (ULONG_PTR *table,int index)';
# and then dereference themselves. Latter shall result in endless
# loop *unless* OPENSSL_Uplink does not replace 'table[index]' with
# something else, e.g. as 'table[index]=unimplemented;'...
$arg = shift;
#( defined shift || open STDOUT,">$arg" ) || die "can't open $arg: $!";
if ($arg =~ /win32n/) { ia32nasm(); }
elsif ($arg =~ /win32/) { ia32masm(); }
elsif ($arg =~ /coff/) { ia32gas(); }
elsif ($arg =~ /win64i/ or $arg =~ /ia64/) { ia64ias(); }
elsif ($arg =~ /win64a/ or $arg =~ /amd64/) { amd64masm(); }
else { die "nonsense $arg"; }
sub ia32gas() {
print <<___;
.text
___
for ($i=1;$i<=$N;$i++) {
print <<___;
.def .Lazy$i; .scl 3; .type 32; .endef
.align 4
.Lazy$i:
pushl \$$i
pushl \$_OPENSSL_UplinkTable
call _OPENSSL_Uplink
addl \$8,%esp
jmp *(_OPENSSL_UplinkTable+4*$i)
___
}
print <<___;
.data
.align 4
.globl _OPENSSL_UplinkTable
_OPENSSL_UplinkTable:
.long $N
___
for ($i=1;$i<=$N;$i++) { print " .long .Lazy$i\n"; }
}
sub ia32masm() {
print <<___;
.386P
.model FLAT
_DATA SEGMENT
PUBLIC _OPENSSL_UplinkTable
_OPENSSL_UplinkTable DD $N ; amount of following entries
___
for ($i=1;$i<=$N;$i++) { print " DD FLAT:\$lazy$i\n"; }
print <<___;
_DATA ENDS
_TEXT SEGMENT
EXTRN _OPENSSL_Uplink:NEAR
___
for ($i=1;$i<=$N;$i++) {
print <<___;
ALIGN 4
\$lazy$i PROC NEAR
push $i
push OFFSET FLAT:_OPENSSL_UplinkTable
call _OPENSSL_Uplink
add esp,8
jmp DWORD PTR _OPENSSL_UplinkTable+4*$i
\$lazy$i ENDP
___
}
print <<___;
ALIGN 4
_TEXT ENDS
END
___
}
sub ia32nasm() {
print <<___;
SEGMENT .data
GLOBAL _OPENSSL_UplinkTable
_OPENSSL_UplinkTable DD $N ; amount of following entries
___
for ($i=1;$i<=$N;$i++) { print " DD \$lazy$i\n"; }
print <<___;
SEGMENT .text
EXTERN _OPENSSL_Uplink
___
for ($i=1;$i<=$N;$i++) {
print <<___;
ALIGN 4
\$lazy$i:
push $i
push _OPENSSL_UplinkTable
call _OPENSSL_Uplink
add esp,8
jmp [_OPENSSL_UplinkTable+4*$i]
___
}
print <<___;
ALIGN 4
END
___
}
sub ia64ias () {
local $V=8; # max number of args uplink functions may accept...
print <<___;
.data
.global OPENSSL_UplinkTable#
OPENSSL_UplinkTable: data8 $N // amount of following entries
___
for ($i=1;$i<=$N;$i++) { print " data8 \@fptr(lazy$i#)\n"; }
print <<___;
.size OPENSSL_UplinkTable,.-OPENSSL_UplinkTable#
.text
.global OPENSSL_Uplink#
.type OPENSSL_Uplink#,\@function
___
for ($i=1;$i<=$N;$i++) {
print <<___;
.proc lazy$i
lazy$i:
{ .mii; alloc loc0=ar.pfs,$V,3,2,0
mov loc1=b0
addl loc2=\@ltoff(OPENSSL_UplinkTable#),gp };;
{ .mmi; ld8 out0=[loc2]
mov out1=$i };;
{ .mib; adds loc2=8*$i,out0
br.call.sptk.many b0=OPENSSL_Uplink# };;
{ .mmi; ld8 r31=[loc2];;
ld8 r30=[r31],8 };;
{ .mii; ld8 gp=[r31]
mov b6=r30
mov b0=loc1 };;
{ .mib; mov ar.pfs=loc0
br.many b6 };;
.endp lazy$i#
___
}
}
sub amd64masm() {
print <<___;
_DATA SEGMENT
PUBLIC OPENSSL_UplinkTable
OPENSSL_UplinkTable DQ $N
___
for ($i=1;$i<=$N;$i++) { print " DQ \$lazy$i\n"; }
print <<___;
_DATA ENDS
_TEXT SEGMENT
EXTERN OPENSSL_Uplink:PROC
___
for ($i=1;$i<=$N;$i++) {
print <<___;
ALIGN 4
\$lazy$i PROC
push r9
push r8
push rdx
push rcx
sub rsp,40
lea rcx,OFFSET OPENSSL_UplinkTable
mov rdx,$i
call OPENSSL_Uplink
add rsp,40
pop rcx
pop rdx
pop r8
pop r9
jmp QWORD PTR OPENSSL_UplinkTable+8*$i
\$lazy$i ENDP
___
}
print <<___;
_TEXT ENDS
END
___
}
|