~andersk/ubuntu/oneiric/openssl/spurious-reboot

« back to all changes in this revision

Viewing changes to .pc/kfreebsd-pipe.patch/crypto/perlasm/x86_64-xlate.pl

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2011-05-01 23:51:53 UTC
  • mfrom: (11.1.20 sid)
  • Revision ID: james.westby@ubuntu.com-20110501235153-bjcxitndquaezb68
Tags: 1.0.0d-2ubuntu1
* Resynchronise with Debian (LP: #675566).  Remaining changes:
  - debian/libssl1.0.0.postinst:
    + Display a system restart required notification bubble on libssl1.0.0
      upgrade.
    + Use a different priority for libssl1.0.0/restart-services depending
      on whether a desktop, or server dist-upgrade is being performed.
  - debian/{libssl1.0.0-udeb.dirs, control, rules}: Create
    libssl1.0.0-udeb, for the benefit of wget-udeb (no wget-udeb package
    in Debian).
  - debian/{libcrypto1.0.0-udeb.dirs, libssl1.0.0.dirs, libssl1.0.0.files,
    rules}: Move runtime libraries to /lib, for the benefit of
    wpasupplicant.
  - debian/patches/aesni.patch: Backport Intel AES-NI support, now from
    http://rt.openssl.org/Ticket/Display.html?id=2065 rather than the
    0.9.8 variant.
  - debian/patches/Bsymbolic-functions.patch: Link using
    -Bsymbolic-functions.
  - debian/patches/perlpath-quilt.patch: Don't change perl #! paths under
    .pc.
  - debian/rules:
    + Don't run 'make test' when cross-building.
    + Use host compiler when cross-building.  Patch from Neil Williams.
    + Don't build for processors no longer supported: i486, i586 (on
      i386), v8 (on sparc).
    + Fix Makefile to properly clean up libs/ dirs in clean target.
    + Replace duplicate files in the doc directory with symlinks.
* Update architectures affected by Bsymbolic-functions.patch.
* Drop debian/patches/no-sslv2.patch; Debian now adds the 'no-ssl2'
  configure option, which compiles out SSLv2 support entirely, so this is
  no longer needed.
* Drop openssl-doc in favour of the libssl-doc package introduced by
  Debian.  Add Conflicts/Replaces until the next LTS release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env perl
2
2
 
3
 
# Ascetic x86_64 AT&T to MASM assembler translator by <appro>.
 
3
# Ascetic x86_64 AT&T to MASM/NASM assembler translator by <appro>.
4
4
#
5
5
# Why AT&T to MASM and not vice versa? Several reasons. Because AT&T
6
6
# format is way easier to parse. Because it's simpler to "gear" from
20
20
# Currently recognized limitations:
21
21
#
22
22
# - can't use multiple ops per line;
23
 
# - indirect calls and jumps are not supported;
24
23
#
25
24
# Dual-ABI styling rules.
26
25
#
27
 
# 1. Adhere to Unix register and stack layout [see the end for
28
 
#    explanation].
 
26
# 1. Adhere to Unix register and stack layout [see cross-reference
 
27
#    ABI "card" at the end for explanation].
29
28
# 2. Forget about "red zone," stick to more traditional blended
30
29
#    stack frame allocation. If volatile storage is actually required
31
30
#    that is. If not, just leave the stack as is.
42
41
# 6. Don't use [or hand-code with .byte] "rep ret." "ret" mnemonic is
43
42
#    required to identify the spots, where to inject Win64 epilogue!
44
43
#    But on the pros, it's then prefixed with rep automatically:-)
45
 
# 7. Due to MASM limitations [and certain general counter-intuitivity
46
 
#    of ip-relative addressing] generation of position-independent
47
 
#    code is assisted by synthetic directive, .picmeup, which puts
48
 
#    address of the *next* instruction into target register.
 
44
# 7. Stick to explicit ip-relative addressing. If you have to use
 
45
#    GOTPCREL addressing, stick to mov symbol@GOTPCREL(%rip),%r??.
 
46
#    Both are recognized and translated to proper Win64 addressing
 
47
#    modes. To support legacy code a synthetic directive, .picmeup,
 
48
#    is implemented. It puts address of the *next* instruction into
 
49
#    target register, e.g.:
49
50
#
50
 
#    Example 1:
51
51
#               .picmeup        %rax
52
52
#               lea             .Label-.(%rax),%rax
53
 
#    Example 2:
54
 
#               .picmeup        %rcx
55
 
#       .Lpic_point:
56
 
#               ...
57
 
#               lea             .Label-.Lpic_point(%rcx),%rbp
58
 
 
59
 
my $output = shift;
 
53
#
 
54
# 8. In order to provide for structured exception handling unified
 
55
#    Win64 prologue copies %rsp value to %rax. For further details
 
56
#    see SEH paragraph at the end.
 
57
# 9. .init segment is allowed to contain calls to functions only.
 
58
# a. If function accepts more than 4 arguments *and* >4th argument
 
59
#    is declared as non 64-bit value, do clear its upper part.
 
60
 
 
61
my $flavour = shift;
 
62
my $output  = shift;
 
63
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
60
64
 
61
65
{ my ($stddev,$stdino,@junk)=stat(STDOUT);
62
66
  my ($outdev,$outino,@junk)=stat($output);
65
69
        if ($stddev!=$outdev || $stdino!=$outino);
66
70
}
67
71
 
 
72
my $gas=1;      $gas=0 if ($output =~ /\.asm$/);
 
73
my $elf=1;      $elf=0 if (!$gas);
 
74
my $win64=0;
 
75
my $prefix="";
 
76
my $decor=".L";
 
77
 
68
78
my $masmref=8 + 50727*2**-32;   # 8.00.50727 shipped with VS2005
69
 
my $masm=$masmref if ($output =~ /\.asm/);
70
 
if ($masm && `ml64 2>&1` =~ m/Version ([0-9]+)\.([0-9]+)(\.([0-9]+))?/)
71
 
{   $masm=$1 + $2*2**-16 + $4*2**-32;   }
 
79
my $masm=0;
 
80
my $PTR=" PTR";
 
81
 
 
82
my $nasmref=2.03;
 
83
my $nasm=0;
 
84
 
 
85
if    ($flavour eq "mingw64")   { $gas=1; $elf=0; $win64=1;
 
86
                                  $prefix=`echo __USER_LABEL_PREFIX__ | $ENV{CC} -E -P -`;
 
87
                                  chomp($prefix);
 
88
                                }
 
89
elsif ($flavour eq "macosx")    { $gas=1; $elf=0; $prefix="_"; $decor="L\$"; }
 
90
elsif ($flavour eq "masm")      { $gas=0; $elf=0; $masm=$masmref; $win64=1; $decor="\$L\$"; }
 
91
elsif ($flavour eq "nasm")      { $gas=0; $elf=0; $nasm=$nasmref; $win64=1; $decor="\$L\$"; $PTR=""; }
 
92
elsif (!$gas)
 
93
{   if ($ENV{ASM} =~ m/nasm/ && `nasm -v` =~ m/version ([0-9]+)\.([0-9]+)/i)
 
94
    {   $nasm = $1 + $2*0.01; $PTR="";  }
 
95
    elsif (`ml64 2>&1` =~ m/Version ([0-9]+)\.([0-9]+)(\.([0-9]+))?/)
 
96
    {   $masm = $1 + $2*2**-16 + $4*2**-32;   }
 
97
    die "no assembler found on %PATH" if (!($nasm || $masm));
 
98
    $win64=1;
 
99
    $elf=0;
 
100
    $decor="\$L\$";
 
101
}
72
102
 
73
103
my $current_segment;
74
104
my $current_function;
 
105
my %globals;
75
106
 
76
107
{ package opcode;       # pick up opcodes
77
108
    sub re {
88
119
            if ($self->{op} =~ /^(movz)b.*/) {  # movz is pain...
89
120
                $self->{op} = $1;
90
121
                $self->{sz} = "b";
91
 
            } elsif ($self->{op} =~ /call/) {
92
 
                $self->{sz} = ""
 
122
            } elsif ($self->{op} =~ /call|jmp/) {
 
123
                $self->{sz} = "";
 
124
            } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op)/) { # SSEn
 
125
                $self->{sz} = "";
93
126
            } elsif ($self->{op} =~ /([a-z]{3,})([qlwb])$/) {
94
127
                $self->{op} = $1;
95
128
                $self->{sz} = $2;
105
138
    }
106
139
    sub out {
107
140
        my $self = shift;
108
 
        if (!$masm) {
 
141
        if ($gas) {
109
142
            if ($self->{op} eq "movz") {        # movz is pain...
110
143
                sprintf "%s%s%s",$self->{op},$self->{sz},shift;
111
144
            } elsif ($self->{op} =~ /^set/) { 
112
145
                "$self->{op}";
113
146
            } elsif ($self->{op} eq "ret") {
114
 
                ".byte  0xf3,0xc3";
 
147
                my $epilogue = "";
 
148
                if ($win64 && $current_function->{abi} eq "svr4") {
 
149
                    $epilogue = "movq   8(%rsp),%rdi\n\t" .
 
150
                                "movq   16(%rsp),%rsi\n\t";
 
151
                }
 
152
                $epilogue . ".byte      0xf3,0xc3";
 
153
            } elsif ($self->{op} eq "call" && !$elf && $current_segment eq ".init") {
 
154
                ".p2align\t3\n\t.quad";
115
155
            } else {
116
156
                "$self->{op}$self->{sz}";
117
157
            }
119
159
            $self->{op} =~ s/^movz/movzx/;
120
160
            if ($self->{op} eq "ret") {
121
161
                $self->{op} = "";
122
 
                if ($current_function->{abi} eq "svr4") {
123
 
                    $self->{op} = "mov  rdi,QWORD PTR 8[rsp]\t;WIN64 epilogue\n\t".
124
 
                                  "mov  rsi,QWORD PTR 16[rsp]\n\t";
 
162
                if ($win64 && $current_function->{abi} eq "svr4") {
 
163
                    $self->{op} = "mov  rdi,QWORD${PTR}[8+rsp]\t;WIN64 epilogue\n\t".
 
164
                                  "mov  rsi,QWORD${PTR}[16+rsp]\n\t";
125
165
                }
126
166
                $self->{op} .= "DB\t0F3h,0C3h\t\t;repret";
127
 
            }
 
167
            } elsif ($self->{op} =~ /^(pop|push)f/) {
 
168
                $self->{op} .= $self->{sz};
 
169
            } elsif ($self->{op} eq "call" && $current_segment eq ".CRT\$XCU") {
 
170
                $self->{op} = "\tDQ";
 
171
            } 
128
172
            $self->{op};
129
173
        }
130
174
    }
 
175
    sub mnemonic {
 
176
        my $self=shift;
 
177
        my $op=shift;
 
178
        $self->{op}=$op if (defined($op));
 
179
        $self->{op};
 
180
    }
131
181
}
132
182
{ package const;        # pick up constants, which start with $
133
183
    sub re {
145
195
    sub out {
146
196
        my $self = shift;
147
197
 
148
 
        if (!$masm) {
 
198
        if ($gas) {
149
199
            # Solaris /usr/ccs/bin/as can't handle multiplications
150
200
            # in $self->{value}
151
 
            $self->{value} =~ s/(?<![0-9a-f])(0[x0-9a-f]+)/oct($1)/egi;
 
201
            $self->{value} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
152
202
            $self->{value} =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg;
153
203
            sprintf "\$%s",$self->{value};
154
204
        } else {
155
 
            $self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig;
 
205
            $self->{value} =~ s/(0b[0-1]+)/oct($1)/eig;
 
206
            $self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm);
156
207
            sprintf "%s",$self->{value};
157
208
        }
158
209
    }
163
214
        local   *line = shift;
164
215
        undef   $ret;
165
216
 
166
 
        if ($line =~ /^([^\(,]*)\(([%\w,]+)\)/) {
167
 
            $self->{label} = $1;
168
 
            ($self->{base},$self->{index},$self->{scale})=split(/,/,$2);
 
217
        # optional * ---vvv--- appears in indirect jmp/call
 
218
        if ($line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)/) {
 
219
            $self->{asterisk} = $1;
 
220
            $self->{label} = $2;
 
221
            ($self->{base},$self->{index},$self->{scale})=split(/,/,$3);
169
222
            $self->{scale} = 1 if (!defined($self->{scale}));
170
223
            $ret = $self;
171
224
            $line = substr($line,@+[0]); $line =~ s/^\s+//;
172
225
 
 
226
            if ($win64 && $self->{label} =~ s/\@GOTPCREL//) {
 
227
                die if (opcode->mnemonic() ne "mov");
 
228
                opcode->mnemonic("lea");
 
229
            }
173
230
            $self->{base}  =~ s/^%//;
174
231
            $self->{index} =~ s/^%// if (defined($self->{index}));
175
232
        }
180
237
        my $self = shift;
181
238
        my $sz = shift;
182
239
 
 
240
        $self->{label} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
 
241
        $self->{label} =~ s/\.L/$decor/g;
 
242
 
183
243
        # Silently convert all EAs to 64-bit. This is required for
184
244
        # elder GNU assembler and results in more compact code,
185
245
        # *but* most importantly AES module depends on this feature!
186
246
        $self->{index} =~ s/^[er](.?[0-9xpi])[d]?$/r\1/;
187
247
        $self->{base}  =~ s/^[er](.?[0-9xpi])[d]?$/r\1/;
188
248
 
189
 
        if (!$masm) {
 
249
        if ($gas) {
190
250
            # Solaris /usr/ccs/bin/as can't handle multiplications
191
 
            # in $self->{label}
 
251
            # in $self->{label}, new gas requires sign extension...
192
252
            use integer;
193
 
            $self->{label} =~ s/(?<![0-9a-f])(0[x0-9a-f]+)/oct($1)/egi;
 
253
            $self->{label} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
194
254
            $self->{label} =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg;
195
255
            $self->{label} =~ s/([0-9]+)/$1<<32>>32/eg;
 
256
            $self->{label} =~ s/^___imp_/__imp__/   if ($flavour eq "mingw64");
196
257
 
197
258
            if (defined($self->{index})) {
198
 
                sprintf "%s(%%%s,%%%s,%d)",
 
259
                sprintf "%s%s(%%%s,%%%s,%d)",$self->{asterisk},
199
260
                                        $self->{label},$self->{base},
200
261
                                        $self->{index},$self->{scale};
201
262
            } else {
202
 
                sprintf "%s(%%%s)",     $self->{label},$self->{base};
 
263
                sprintf "%s%s(%%%s)",   $self->{asterisk},$self->{label},$self->{base};
203
264
            }
204
265
        } else {
205
 
            %szmap = ( b=>"BYTE", w=>"WORD", l=>"DWORD", q=>"QWORD" );
 
266
            %szmap = ( b=>"BYTE$PTR", w=>"WORD$PTR", l=>"DWORD$PTR", q=>"QWORD$PTR" );
206
267
 
207
268
            $self->{label} =~ s/\./\$/g;
208
 
            $self->{label} =~ s/0x([0-9a-f]+)/0$1h/ig;
 
269
            $self->{label} =~ s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/ig;
209
270
            $self->{label} = "($self->{label})" if ($self->{label} =~ /[\*\+\-\/]/);
 
271
            $sz="q" if ($self->{asterisk});
210
272
 
211
273
            if (defined($self->{index})) {
212
 
                sprintf "%s PTR %s[%s*%d+%s]",$szmap{$sz},
213
 
                                        $self->{label},
 
274
                sprintf "%s[%s%s*%d+%s]",$szmap{$sz},
 
275
                                        $self->{label}?"$self->{label}+":"",
214
276
                                        $self->{index},$self->{scale},
215
277
                                        $self->{base};
216
278
            } elsif ($self->{base} eq "rip") {
217
 
                sprintf "%s PTR %s",$szmap{$sz},$self->{label};
 
279
                sprintf "%s[%s]",$szmap{$sz},$self->{label};
218
280
            } else {
219
 
                sprintf "%s PTR %s[%s]",$szmap{$sz},
220
 
                                        $self->{label},$self->{base};
 
281
                sprintf "%s[%s%s]",$szmap{$sz},
 
282
                                        $self->{label}?"$self->{label}+":"",
 
283
                                        $self->{base};
221
284
            }
222
285
        }
223
286
    }
229
292
        local   *line = shift;
230
293
        undef   $ret;
231
294
 
232
 
        if ($line =~ /^%(\w+)/) {
 
295
        # optional * ---vvv--- appears in indirect jmp/call
 
296
        if ($line =~ /^(\*?)%(\w+)/) {
233
297
            bless $self,$class;
234
 
            $self->{value} = $1;
 
298
            $self->{asterisk} = $1;
 
299
            $self->{value} = $2;
235
300
            $ret = $self;
236
301
            $line = substr($line,@+[0]); $line =~ s/^\s+//;
237
302
        }
254
319
    }
255
320
    sub out {
256
321
        my $self = shift;
257
 
        sprintf $masm?"%s":"%%%s",$self->{value};
 
322
        if ($gas)       { sprintf "%s%%%s",$self->{asterisk},$self->{value}; }
 
323
        else            { $self->{value}; }
258
324
    }
259
325
}
260
326
{ package label;        # pick up labels, which end with :
263
329
        local   *line = shift;
264
330
        undef   $ret;
265
331
 
266
 
        if ($line =~ /(^[\.\w]+\:)/) {
 
332
        if ($line =~ /(^[\.\w]+)\:/) {
267
333
            $self->{value} = $1;
268
334
            $ret = $self;
269
335
            $line = substr($line,@+[0]); $line =~ s/^\s+//;
270
336
 
271
 
            $self->{value} =~ s/\.L/\$L/ if ($masm);
 
337
            $self->{value} =~ s/^\.L/$decor/;
272
338
        }
273
339
        $ret;
274
340
    }
275
341
    sub out {
276
342
        my $self = shift;
277
343
 
278
 
        if (!$masm) {
279
 
            $self->{value};
280
 
        } elsif ($self->{value} ne "$current_function->{name}:") {
281
 
            $self->{value};
282
 
        } elsif ($current_function->{abi} eq "svr4") {
283
 
            my $func =  "$current_function->{name}      PROC\n".
284
 
                        "       mov     QWORD PTR 8[rsp],rdi\t;WIN64 prologue\n".
285
 
                        "       mov     QWORD PTR 16[rsp],rsi\n";
 
344
        if ($gas) {
 
345
            my $func = ($globals{$self->{value}} or $self->{value}) . ":";
 
346
            if ($win64  &&
 
347
                        $current_function->{name} eq $self->{value} &&
 
348
                        $current_function->{abi} eq "svr4") {
 
349
                $func .= "\n";
 
350
                $func .= "      movq    %rdi,8(%rsp)\n";
 
351
                $func .= "      movq    %rsi,16(%rsp)\n";
 
352
                $func .= "      movq    %rsp,%rax\n";
 
353
                $func .= "${decor}SEH_begin_$current_function->{name}:\n";
 
354
                my $narg = $current_function->{narg};
 
355
                $narg=6 if (!defined($narg));
 
356
                $func .= "      movq    %rcx,%rdi\n" if ($narg>0);
 
357
                $func .= "      movq    %rdx,%rsi\n" if ($narg>1);
 
358
                $func .= "      movq    %r8,%rdx\n"  if ($narg>2);
 
359
                $func .= "      movq    %r9,%rcx\n"  if ($narg>3);
 
360
                $func .= "      movq    40(%rsp),%r8\n" if ($narg>4);
 
361
                $func .= "      movq    48(%rsp),%r9\n" if ($narg>5);
 
362
            }
 
363
            $func;
 
364
        } elsif ($self->{value} ne "$current_function->{name}") {
 
365
            $self->{value} .= ":" if ($masm && $ret!~m/^\$/);
 
366
            $self->{value} . ":";
 
367
        } elsif ($win64 && $current_function->{abi} eq "svr4") {
 
368
            my $func =  "$current_function->{name}" .
 
369
                        ($nasm ? ":" : "\tPROC $current_function->{scope}") .
 
370
                        "\n";
 
371
            $func .= "  mov     QWORD${PTR}[8+rsp],rdi\t;WIN64 prologue\n";
 
372
            $func .= "  mov     QWORD${PTR}[16+rsp],rsi\n";
 
373
            $func .= "  mov     rax,rsp\n";
 
374
            $func .= "${decor}SEH_begin_$current_function->{name}:";
 
375
            $func .= ":" if ($masm);
 
376
            $func .= "\n";
286
377
            my $narg = $current_function->{narg};
287
378
            $narg=6 if (!defined($narg));
288
379
            $func .= "  mov     rdi,rcx\n" if ($narg>0);
289
380
            $func .= "  mov     rsi,rdx\n" if ($narg>1);
290
381
            $func .= "  mov     rdx,r8\n"  if ($narg>2);
291
382
            $func .= "  mov     rcx,r9\n"  if ($narg>3);
292
 
            $func .= "  mov     r8,QWORD PTR 40[rsp]\n" if ($narg>4);
293
 
            $func .= "  mov     r9,QWORD PTR 48[rsp]\n" if ($narg>5);
 
383
            $func .= "  mov     r8,QWORD${PTR}[40+rsp]\n" if ($narg>4);
 
384
            $func .= "  mov     r9,QWORD${PTR}[48+rsp]\n" if ($narg>5);
294
385
            $func .= "\n";
295
386
        } else {
296
 
           "$current_function->{name}   PROC";
 
387
           "$current_function->{name}".
 
388
                        ($nasm ? ":" : "\tPROC $current_function->{scope}");
297
389
        }
298
390
    }
299
391
}
308
400
            $ret = $self;
309
401
            $line = substr($line,@+[0]); $line =~ s/^\s+//;
310
402
 
311
 
            $self->{value} =~ s/\.L/\$L/g if ($masm);
 
403
            $self->{value} =~ s/\@PLT// if (!$elf);
 
404
            $self->{value} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
 
405
            $self->{value} =~ s/\.L/$decor/g;
312
406
        }
313
407
        $ret;
314
408
    }
315
409
    sub out {
316
410
        my $self = shift;
317
 
        $self->{value};
 
411
        if ($nasm && opcode->mnemonic()=~m/^j/) {
 
412
            "NEAR ".$self->{value};
 
413
        } else {
 
414
            $self->{value};
 
415
        }
318
416
    }
319
417
}
320
418
{ package directive;    # pick up directives, which start with .
334
432
                        "%r14"=>0x01358d4c,     "%r15"=>0x013d8d4c      );
335
433
 
336
434
        if ($line =~ /^\s*(\.\w+)/) {
337
 
            if (!$masm) {
338
 
                $self->{value} = $1;
339
 
                $line =~ s/\@abi\-omnipotent/\@function/;
340
 
                $line =~ s/\@function.*/\@function/;
341
 
                if ($line =~ /\.picmeup\s+(%r[\w]+)/i) {
342
 
                    $self->{value} = sprintf "\t.long\t0x%x,0x90000000",$opcode{$1};
343
 
                } elsif ($line =~ /\.asciz\s+"(.*)"$/) {
344
 
                    $self->{value} = ".byte\t".join(",",unpack("C*",$1),0);
345
 
                } elsif ($line =~ /\.extern/) {
346
 
                    $self->{value} = ""; # swallow extern
347
 
                } else {
348
 
                    $self->{value} = $line;
349
 
                }
350
 
                $line = "";
351
 
                return $self;
352
 
            }
353
 
 
354
435
            $dir = $1;
355
436
            $ret = $self;
356
437
            undef $self->{value};
357
438
            $line = substr($line,@+[0]); $line =~ s/^\s+//;
 
439
 
358
440
            SWITCH: for ($dir) {
359
 
                /\.(text)/
360
 
                            && do { my $v=undef;
361
 
                                    $v="$current_segment\tENDS\n" if ($current_segment);
362
 
                                    $current_segment = "_$1\$";
363
 
                                    $current_segment =~ tr/[a-z]/[A-Z]/;
364
 
                                    $v.="$current_segment\tSEGMENT ";
365
 
                                    $v.=$masm>=$masmref ? "ALIGN(64)" : "PAGE";
366
 
                                    $v.=" 'CODE'";
367
 
                                    $self->{value} = $v;
368
 
                                    last;
369
 
                                  };
370
 
                /\.extern/  && do { $self->{value} = "EXTRN\t".$line.":BYTE"; last;  };
371
 
                /\.globl/   && do { $self->{value} = "PUBLIC\t".$line; last; };
 
441
                /\.picmeup/ && do { if ($line =~ /(%r[\w]+)/i) {
 
442
                                        $dir="\t.long";
 
443
                                        $line=sprintf "0x%x,0x90000000",$opcode{$1};
 
444
                                    }
 
445
                                    last;
 
446
                                  };
 
447
                /\.global|\.globl|\.extern/
 
448
                            && do { $globals{$line} = $prefix . $line;
 
449
                                    $line = $globals{$line} if ($prefix);
 
450
                                    last;
 
451
                                  };
372
452
                /\.type/    && do { ($sym,$type,$narg) = split(',',$line);
373
453
                                    if ($type eq "\@function") {
374
454
                                        undef $current_function;
375
455
                                        $current_function->{name} = $sym;
376
456
                                        $current_function->{abi}  = "svr4";
377
457
                                        $current_function->{narg} = $narg;
 
458
                                        $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE";
378
459
                                    } elsif ($type eq "\@abi-omnipotent") {
379
460
                                        undef $current_function;
380
461
                                        $current_function->{name} = $sym;
381
 
                                    }
 
462
                                        $current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE";
 
463
                                    }
 
464
                                    $line =~ s/\@abi\-omnipotent/\@function/;
 
465
                                    $line =~ s/\@function.*/\@function/;
 
466
                                    last;
 
467
                                  };
 
468
                /\.asciz/   && do { if ($line =~ /^"(.*)"$/) {
 
469
                                        $dir  = ".byte";
 
470
                                        $line = join(",",unpack("C*",$1),0);
 
471
                                    }
 
472
                                    last;
 
473
                                  };
 
474
                /\.rva|\.long|\.quad/
 
475
                            && do { $line =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
 
476
                                    $line =~ s/\.L/$decor/g;
 
477
                                    last;
 
478
                                  };
 
479
            }
 
480
 
 
481
            if ($gas) {
 
482
                $self->{value} = $dir . "\t" . $line;
 
483
 
 
484
                if ($dir =~ /\.extern/) {
 
485
                    $self->{value} = ""; # swallow extern
 
486
                } elsif (!$elf && $dir =~ /\.type/) {
 
487
                    $self->{value} = "";
 
488
                    $self->{value} = ".def\t" . ($globals{$1} or $1) . ";\t" .
 
489
                                (defined($globals{$1})?".scl 2;":".scl 3;") .
 
490
                                "\t.type 32;\t.endef"
 
491
                                if ($win64 && $line =~ /([^,]+),\@function/);
 
492
                } elsif (!$elf && $dir =~ /\.size/) {
 
493
                    $self->{value} = "";
 
494
                    if (defined($current_function)) {
 
495
                        $self->{value} .= "${decor}SEH_end_$current_function->{name}:"
 
496
                                if ($win64 && $current_function->{abi} eq "svr4");
 
497
                        undef $current_function;
 
498
                    }
 
499
                } elsif (!$elf && $dir =~ /\.align/) {
 
500
                    $self->{value} = ".p2align\t" . (log($line)/log(2));
 
501
                } elsif ($dir eq ".section") {
 
502
                    $current_segment=$line;
 
503
                    if (!$elf && $current_segment eq ".init") {
 
504
                        if      ($flavour eq "macosx")  { $self->{value} = ".mod_init_func"; }
 
505
                        elsif   ($flavour eq "mingw64") { $self->{value} = ".section\t.ctors"; }
 
506
                    }
 
507
                } elsif ($dir =~ /\.(text|data)/) {
 
508
                    $current_segment=".$1";
 
509
                }
 
510
                $line = "";
 
511
                return $self;
 
512
            }
 
513
 
 
514
            # non-gas case or nasm/masm
 
515
            SWITCH: for ($dir) {
 
516
                /\.text/    && do { my $v=undef;
 
517
                                    if ($nasm) {
 
518
                                        $v="section     .text code align=64\n";
 
519
                                    } else {
 
520
                                        $v="$current_segment\tENDS\n" if ($current_segment);
 
521
                                        $current_segment = ".text\$";
 
522
                                        $v.="$current_segment\tSEGMENT ";
 
523
                                        $v.=$masm>=$masmref ? "ALIGN(64)" : "PAGE";
 
524
                                        $v.=" 'CODE'";
 
525
                                    }
 
526
                                    $self->{value} = $v;
 
527
                                    last;
 
528
                                  };
 
529
                /\.data/    && do { my $v=undef;
 
530
                                    if ($nasm) {
 
531
                                        $v="section     .data data align=8\n";
 
532
                                    } else {
 
533
                                        $v="$current_segment\tENDS\n" if ($current_segment);
 
534
                                        $current_segment = "_DATA";
 
535
                                        $v.="$current_segment\tSEGMENT";
 
536
                                    }
 
537
                                    $self->{value} = $v;
 
538
                                    last;
 
539
                                  };
 
540
                /\.section/ && do { my $v=undef;
 
541
                                    $line =~ s/([^,]*).*/$1/;
 
542
                                    $line = ".CRT\$XCU" if ($line eq ".init");
 
543
                                    if ($nasm) {
 
544
                                        $v="section     $line";
 
545
                                        if ($line=~/\.([px])data/) {
 
546
                                            $v.=" rdata align=";
 
547
                                            $v.=$1 eq "p"? 4 : 8;
 
548
                                        } elsif ($line=~/\.CRT\$/i) {
 
549
                                            $v.=" rdata align=8";
 
550
                                        }
 
551
                                    } else {
 
552
                                        $v="$current_segment\tENDS\n" if ($current_segment);
 
553
                                        $v.="$line\tSEGMENT";
 
554
                                        if ($line=~/\.([px])data/) {
 
555
                                            $v.=" READONLY";
 
556
                                            $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref);
 
557
                                        } elsif ($line=~/\.CRT\$/i) {
 
558
                                            $v.=" READONLY DWORD";
 
559
                                        }
 
560
                                    }
 
561
                                    $current_segment = $line;
 
562
                                    $self->{value} = $v;
 
563
                                    last;
 
564
                                  };
 
565
                /\.extern/  && do { $self->{value}  = "EXTERN\t".$line;
 
566
                                    $self->{value} .= ":NEAR" if ($masm);
 
567
                                    last;
 
568
                                  };
 
569
                /\.globl|.global/
 
570
                            && do { $self->{value}  = $masm?"PUBLIC":"global";
 
571
                                    $self->{value} .= "\t".$line;
382
572
                                    last;
383
573
                                  };
384
574
                /\.size/    && do { if (defined($current_function)) {
385
 
                                        $self->{value}="$current_function->{name}\tENDP";
 
575
                                        undef $self->{value};
 
576
                                        if ($current_function->{abi} eq "svr4") {
 
577
                                            $self->{value}="${decor}SEH_end_$current_function->{name}:";
 
578
                                            $self->{value}.=":\n" if($masm);
 
579
                                        }
 
580
                                        $self->{value}.="$current_function->{name}\tENDP" if($masm);
386
581
                                        undef $current_function;
387
582
                                    }
388
583
                                    last;
389
584
                                  };
390
585
                /\.align/   && do { $self->{value} = "ALIGN\t".$line; last; };
391
 
                /\.(byte|value|long|quad)/
392
 
                            && do { my @arr = split(',',$line);
393
 
                                    my $sz  = substr($1,0,1);
 
586
                /\.(value|long|rva|quad)/
 
587
                            && do { my $sz  = substr($1,0,1);
 
588
                                    my @arr = split(/,\s*/,$line);
394
589
                                    my $last = pop(@arr);
395
590
                                    my $conv = sub  {   my $var=shift;
396
 
                                                        if ($var=~s/0x([0-9a-f]+)/0$1h/i) { $var; }
397
 
                                                        else { sprintf"0%Xh",$var; }
 
591
                                                        $var=~s/^(0b[0-1]+)/oct($1)/eig;
 
592
                                                        $var=~s/^0x([0-9a-f]+)/0$1h/ig if ($masm);
 
593
                                                        if ($sz eq "D" && ($current_segment=~/.[px]data/ || $dir eq ".rva"))
 
594
                                                        { $var=~s/([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; }
 
595
                                                        $var;
398
596
                                                    };  
399
597
 
400
 
                                    $sz =~ tr/bvlq/BWDQ/;
 
598
                                    $sz =~ tr/bvlrq/BWDDQ/;
401
599
                                    $self->{value} = "\tD$sz\t";
402
600
                                    for (@arr) { $self->{value} .= &$conv($_).","; }
403
601
                                    $self->{value} .= &$conv($last);
404
602
                                    last;
405
603
                                  };
406
 
                /\.picmeup/ && do { $self->{value} = sprintf"\tDD\t 0%Xh,090000000h",$opcode{$line};
407
 
                                    last;
408
 
                                  };
409
 
                /\.asciz/   && do { if ($line =~ /^"(.*)"$/) {
410
 
                                        my @str=unpack("C*",$1);
411
 
                                        push @str,0;
412
 
                                        while ($#str>15) {
413
 
                                            $self->{value}.="DB\t"
 
604
                /\.byte/    && do { my @str=split(/,\s*/,$line);
 
605
                                    map(s/(0b[0-1]+)/oct($1)/eig,@str);
 
606
                                    map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm);       
 
607
                                    while ($#str>15) {
 
608
                                        $self->{value}.="DB\t"
414
609
                                                .join(",",@str[0..15])."\n";
415
 
                                            foreach (0..15) { shift @str; }
416
 
                                        }
417
 
                                        $self->{value}.="DB\t"
 
610
                                        foreach (0..15) { shift @str; }
 
611
                                    }
 
612
                                    $self->{value}.="DB\t"
418
613
                                                .join(",",@str) if (@str);
419
 
                                    }
420
614
                                    last;
421
615
                                  };
422
616
            }
431
625
    }
432
626
}
433
627
 
 
628
if ($nasm) {
 
629
    print <<___;
 
630
default rel
 
631
___
 
632
} elsif ($masm) {
 
633
    print <<___;
 
634
OPTION  DOTNAME
 
635
___
 
636
}
434
637
while($line=<>) {
435
638
 
436
639
    chomp($line);
441
644
 
442
645
    undef $label;
443
646
    undef $opcode;
444
 
    undef $dst;
445
 
    undef $src;
446
647
    undef $sz;
 
648
    undef @args;
447
649
 
448
650
    if ($label=label->re(\$line))       { print $label->out(); }
449
651
 
450
652
    if (directive->re(\$line)) {
451
653
        printf "%s",directive->out();
452
 
    } elsif ($opcode=opcode->re(\$line)) { ARGUMENT: {
453
 
 
454
 
        if ($src=register->re(\$line))  { opcode->size($src->size()); }
455
 
        elsif ($src=const->re(\$line))  { }
456
 
        elsif ($src=ea->re(\$line))     { }
457
 
        elsif ($src=expr->re(\$line))   { }
 
654
    } elsif ($opcode=opcode->re(\$line)) { ARGUMENT: while (1) {
 
655
        my $arg;
 
656
 
 
657
        if ($arg=register->re(\$line))  { opcode->size($arg->size()); }
 
658
        elsif ($arg=const->re(\$line))  { }
 
659
        elsif ($arg=ea->re(\$line))     { }
 
660
        elsif ($arg=expr->re(\$line))   { }
 
661
        else                            { last ARGUMENT; }
 
662
 
 
663
        push @args,$arg;
458
664
 
459
665
        last ARGUMENT if ($line !~ /^,/);
460
666
 
461
 
        $line = substr($line,1); $line =~ s/^\s+//;
462
 
 
463
 
        if ($dst=register->re(\$line))  { opcode->size($dst->size()); }
464
 
        elsif ($dst=const->re(\$line))  { }
465
 
        elsif ($dst=ea->re(\$line))     { }
466
 
 
 
667
        $line =~ s/^,\s*//;
467
668
        } # ARGUMENT:
468
669
 
469
670
        $sz=opcode->size();
470
671
 
471
 
        if (defined($dst)) {
472
 
            if (!$masm) {
473
 
                printf "\t%s\t%s,%s",   $opcode->out($dst->size()),
474
 
                                        $src->out($sz),$dst->out($sz);
 
672
        if ($#args>=0) {
 
673
            my $insn;
 
674
            if ($gas) {
 
675
                $insn = $opcode->out($#args>=1?$args[$#args]->size():$sz);
475
676
            } else {
476
 
                printf "\t%s\t%s,%s",   $opcode->out(),
477
 
                                        $dst->out($sz),$src->out($sz);
 
677
                $insn = $opcode->out();
 
678
                $insn .= $sz if (map($_->out() =~ /x?mm/,@args));
 
679
                @args = reverse(@args);
 
680
                undef $sz if ($nasm && $opcode->mnemonic() eq "lea");
478
681
            }
479
 
        } elsif (defined($src)) {
480
 
            printf "\t%s\t%s",$opcode->out(),$src->out($sz);
 
682
            printf "\t%s\t%s",$insn,join(",",map($_->out($sz),@args));
481
683
        } else {
482
684
            printf "\t%s",$opcode->out();
483
685
        }
486
688
    print $line,"\n";
487
689
}
488
690
 
489
 
print "\n$current_segment\tENDS\nEND\n" if ($masm);
 
691
print "\n$current_segment\tENDS\n"      if ($current_segment && $masm);
 
692
print "END\n"                           if ($masm);
490
693
 
491
694
close STDOUT;
492
695
 
493
 
#################################################
 
696
#################################################
494
697
# Cross-reference x86_64 ABI "card"
495
698
#
496
699
#               Unix            Win64
554
757
#       movq    16(%rsp),%rsi
555
758
# endif
556
759
#       ret
 
760
#
 
761
#################################################
 
762
# Win64 SEH, Structured Exception Handling.
 
763
#
 
764
# Unlike on Unix systems(*) lack of Win64 stack unwinding information
 
765
# has undesired side-effect at run-time: if an exception is raised in
 
766
# assembler subroutine such as those in question (basically we're
 
767
# referring to segmentation violations caused by malformed input
 
768
# parameters), the application is briskly terminated without invoking
 
769
# any exception handlers, most notably without generating memory dump
 
770
# or any user notification whatsoever. This poses a problem. It's
 
771
# possible to address it by registering custom language-specific
 
772
# handler that would restore processor context to the state at
 
773
# subroutine entry point and return "exception is not handled, keep
 
774
# unwinding" code. Writing such handler can be a challenge... But it's
 
775
# doable, though requires certain coding convention. Consider following
 
776
# snippet:
 
777
#
 
778
# .type function,@function
 
779
# function:
 
780
#       movq    %rsp,%rax       # copy rsp to volatile register
 
781
#       pushq   %r15            # save non-volatile registers
 
782
#       pushq   %rbx
 
783
#       pushq   %rbp
 
784
#       movq    %rsp,%r11
 
785
#       subq    %rdi,%r11       # prepare [variable] stack frame
 
786
#       andq    $-64,%r11
 
787
#       movq    %rax,0(%r11)    # check for exceptions
 
788
#       movq    %r11,%rsp       # allocate [variable] stack frame
 
789
#       movq    %rax,0(%rsp)    # save original rsp value
 
790
# magic_point:
 
791
#       ...
 
792
#       movq    0(%rsp),%rcx    # pull original rsp value
 
793
#       movq    -24(%rcx),%rbp  # restore non-volatile registers
 
794
#       movq    -16(%rcx),%rbx
 
795
#       movq    -8(%rcx),%r15
 
796
#       movq    %rcx,%rsp       # restore original rsp
 
797
#       ret
 
798
# .size function,.-function
 
799
#
 
800
# The key is that up to magic_point copy of original rsp value remains
 
801
# in chosen volatile register and no non-volatile register, except for
 
802
# rsp, is modified. While past magic_point rsp remains constant till
 
803
# the very end of the function. In this case custom language-specific
 
804
# exception handler would look like this:
 
805
#
 
806
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
 
807
#               CONTEXT *context,DISPATCHER_CONTEXT *disp)
 
808
# {     ULONG64 *rsp = (ULONG64 *)context->Rax;
 
809
#       if (context->Rip >= magic_point)
 
810
#       {   rsp = ((ULONG64 **)context->Rsp)[0];
 
811
#           context->Rbp = rsp[-3];
 
812
#           context->Rbx = rsp[-2];
 
813
#           context->R15 = rsp[-1];
 
814
#       }
 
815
#       context->Rsp = (ULONG64)rsp;
 
816
#       context->Rdi = rsp[1];
 
817
#       context->Rsi = rsp[2];
 
818
#
 
819
#       memcpy (disp->ContextRecord,context,sizeof(CONTEXT));
 
820
#       RtlVirtualUnwind(UNW_FLAG_NHANDLER,disp->ImageBase,
 
821
#               dips->ControlPc,disp->FunctionEntry,disp->ContextRecord,
 
822
#               &disp->HandlerData,&disp->EstablisherFrame,NULL);
 
823
#       return ExceptionContinueSearch;
 
824
# }
 
825
#
 
826
# It's appropriate to implement this handler in assembler, directly in
 
827
# function's module. In order to do that one has to know members'
 
828
# offsets in CONTEXT and DISPATCHER_CONTEXT structures and some constant
 
829
# values. Here they are:
 
830
#
 
831
#       CONTEXT.Rax                             120
 
832
#       CONTEXT.Rcx                             128
 
833
#       CONTEXT.Rdx                             136
 
834
#       CONTEXT.Rbx                             144
 
835
#       CONTEXT.Rsp                             152
 
836
#       CONTEXT.Rbp                             160
 
837
#       CONTEXT.Rsi                             168
 
838
#       CONTEXT.Rdi                             176
 
839
#       CONTEXT.R8                              184
 
840
#       CONTEXT.R9                              192
 
841
#       CONTEXT.R10                             200
 
842
#       CONTEXT.R11                             208
 
843
#       CONTEXT.R12                             216
 
844
#       CONTEXT.R13                             224
 
845
#       CONTEXT.R14                             232
 
846
#       CONTEXT.R15                             240
 
847
#       CONTEXT.Rip                             248
 
848
#       CONTEXT.Xmm6                            512
 
849
#       sizeof(CONTEXT)                         1232
 
850
#       DISPATCHER_CONTEXT.ControlPc            0
 
851
#       DISPATCHER_CONTEXT.ImageBase            8
 
852
#       DISPATCHER_CONTEXT.FunctionEntry        16
 
853
#       DISPATCHER_CONTEXT.EstablisherFrame     24
 
854
#       DISPATCHER_CONTEXT.TargetIp             32
 
855
#       DISPATCHER_CONTEXT.ContextRecord        40
 
856
#       DISPATCHER_CONTEXT.LanguageHandler      48
 
857
#       DISPATCHER_CONTEXT.HandlerData          56
 
858
#       UNW_FLAG_NHANDLER                       0
 
859
#       ExceptionContinueSearch                 1
 
860
#
 
861
# In order to tie the handler to the function one has to compose
 
862
# couple of structures: one for .xdata segment and one for .pdata.
 
863
#
 
864
# UNWIND_INFO structure for .xdata segment would be
 
865
#
 
866
# function_unwind_info:
 
867
#       .byte   9,0,0,0
 
868
#       .rva    handler
 
869
#
 
870
# This structure designates exception handler for a function with
 
871
# zero-length prologue, no stack frame or frame register.
 
872
#
 
873
# To facilitate composing of .pdata structures, auto-generated "gear"
 
874
# prologue copies rsp value to rax and denotes next instruction with
 
875
# .LSEH_begin_{function_name} label. This essentially defines the SEH
 
876
# styling rule mentioned in the beginning. Position of this label is
 
877
# chosen in such manner that possible exceptions raised in the "gear"
 
878
# prologue would be accounted to caller and unwound from latter's frame.
 
879
# End of function is marked with respective .LSEH_end_{function_name}
 
880
# label. To summarize, .pdata segment would contain
 
881
#
 
882
#       .rva    .LSEH_begin_function
 
883
#       .rva    .LSEH_end_function
 
884
#       .rva    function_unwind_info
 
885
#
 
886
# Reference to functon_unwind_info from .xdata segment is the anchor.
 
887
# In case you wonder why references are 32-bit .rvas and not 64-bit
 
888
# .quads. References put into these two segments are required to be
 
889
# *relative* to the base address of the current binary module, a.k.a.
 
890
# image base. No Win64 module, be it .exe or .dll, can be larger than
 
891
# 2GB and thus such relative references can be and are accommodated in
 
892
# 32 bits.
 
893
#
 
894
# Having reviewed the example function code, one can argue that "movq
 
895
# %rsp,%rax" above is redundant. It is not! Keep in mind that on Unix
 
896
# rax would contain an undefined value. If this "offends" you, use
 
897
# another register and refrain from modifying rax till magic_point is
 
898
# reached, i.e. as if it was a non-volatile register. If more registers
 
899
# are required prior [variable] frame setup is completed, note that
 
900
# nobody says that you can have only one "magic point." You can
 
901
# "liberate" non-volatile registers by denoting last stack off-load
 
902
# instruction and reflecting it in finer grade unwind logic in handler.
 
903
# After all, isn't it why it's called *language-specific* handler...
 
904
#
 
905
# Attentive reader can notice that exceptions would be mishandled in
 
906
# auto-generated "gear" epilogue. Well, exception effectively can't
 
907
# occur there, because if memory area used by it was subject to
 
908
# segmentation violation, then it would be raised upon call to the
 
909
# function (and as already mentioned be accounted to caller, which is
 
910
# not a problem). If you're still not comfortable, then define tail
 
911
# "magic point" just prior ret instruction and have handler treat it...
 
912
#
 
913
# (*)   Note that we're talking about run-time, not debug-time. Lack of
 
914
#       unwind information makes debugging hard on both Windows and
 
915
#       Unix. "Unlike" referes to the fact that on Unix signal handler
 
916
#       will always be invoked, core dumped and appropriate exit code
 
917
#       returned to parent (for user notification).