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