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/env 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
___
}
|