
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"; 12: open(INPUT,$applink_c) || die "can't open $applink_c: $!"; 13: @max=grep {/APPLINK_MAX\s+(\d+)/} <INPUT>; 14: close(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: 30: if ($arg =~ /win32n/) { ia32nasm(); } 31: elsif ($arg =~ /win32/) { ia32masm(); } 32: elsif ($arg =~ /coff/) { ia32gas(); } 33: elsif ($arg =~ /win64i/ or $arg =~ /ia64/) { ia64ias(); } 34: elsif ($arg =~ /win64a/ or $arg =~ /amd64/) { amd64masm(); } 35: else { die "nonsense $arg"; } 36: 37: sub ia32gas() { 38: print <<___; 39: .text 40: ___ 41: for ($i=1;$i<=$N;$i++) { 42: print <<___; 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: } 53: print <<___; 54: .data 55: .align 4 56: .globl _OPENSSL_UplinkTable 57: _OPENSSL_UplinkTable: 58: .long $N 59: ___ 60: for ($i=1;$i<=$N;$i++) { print " .long .Lazy$i\n"; } 61: } 62: 63: sub ia32masm() { 64: print <<___; 65: .386P 66: .model FLAT 67: 68: _DATA SEGMENT 69: PUBLIC _OPENSSL_UplinkTable 70: _OPENSSL_UplinkTable DD $N ; amount of following entries 71: ___ 72: for ($i=1;$i<=$N;$i++) { print " DD FLAT:\$lazy$i\n"; } 73: print <<___; 74: _DATA ENDS 75: 76: _TEXT SEGMENT 77: EXTRN _OPENSSL_Uplink:NEAR 78: ___ 79: for ($i=1;$i<=$N;$i++) { 80: print <<___; 81: ALIGN 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: } 91: print <<___; 92: ALIGN 4 93: _TEXT ENDS 94: END 95: ___ 96: } 97: 98: sub ia32nasm() { 99: print <<___; 100: SEGMENT .data 101: GLOBAL _OPENSSL_UplinkTable 102: _OPENSSL_UplinkTable DD $N ; amount of following entries 103: ___ 104: for ($i=1;$i<=$N;$i++) { print " DD \$lazy$i\n"; } 105: print <<___; 106: 107: SEGMENT .text 108: EXTERN _OPENSSL_Uplink 109: ___ 110: for ($i=1;$i<=$N;$i++) { 111: print <<___; 112: ALIGN 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: } 121: print <<___; 122: ALIGN 4 123: END 124: ___ 125: } 126: 127: sub ia64ias () { 128: local $V=8; # max number of args uplink functions may accept... 129: print <<___; 130: .data 131: .global OPENSSL_UplinkTable# 132: OPENSSL_UplinkTable: data8 $N // amount of following entries 133: ___ 134: for ($i=1;$i<=$N;$i++) { print " data8 \@fptr(lazy$i#)\n"; } 135: print <<___; 136: .size OPENSSL_UplinkTable,.-OPENSSL_UplinkTable# 137: 138: .text 139: .global OPENSSL_Uplink# 140: .type OPENSSL_Uplink#,\@function 141: ___ 142: for ($i=1;$i<=$N;$i++) { 143: print <<___; 144: .proc lazy$i 145: lazy$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: 165: sub amd64masm() { 166: print <<___; 167: _DATA SEGMENT 168: PUBLIC OPENSSL_UplinkTable 169: OPENSSL_UplinkTable DQ $N 170: ___ 171: for ($i=1;$i<=$N;$i++) { print " DQ \$lazy$i\n"; } 172: print <<___; 173: _DATA ENDS 174: 175: _TEXT SEGMENT 176: EXTERN OPENSSL_Uplink:PROC 177: ___ 178: for ($i=1;$i<=$N;$i++) { 179: print <<___; 180: ALIGN 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: } 199: print <<___; 200: _TEXT ENDS 201: END 202: ___ 203: } 204: