1#! /usr/bin/env perl 2# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the OpenSSL license (the "License"). You may not use 5# this file except in compliance with the License. You can obtain a copy 6# in the file LICENSE in the source distribution or at 7# https://www.openssl.org/source/license.html 8 9use strict; 10 11my $flavour = shift; 12my $output = shift; 13open STDOUT,">$output" || die "can't open $output: $!"; 14 15$flavour = "linux32" if (!$flavour or $flavour eq "void"); 16 17my %GLOBALS; 18my $dotinlocallabels=($flavour=~/linux/)?1:0; 19 20################################################################ 21# directives which need special treatment on different platforms 22################################################################ 23my $arch = sub { 24 if ($flavour =~ /linux/) { ".arch\t".join(',',@_); } 25 else { ""; } 26}; 27my $fpu = sub { 28 if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); } 29 else { ""; } 30}; 31my $hidden = sub { 32 if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); } 33 else { ".hidden\t".join(',',@_); } 34}; 35my $comm = sub { 36 my @args = split(/,\s*/,shift); 37 my $name = @args[0]; 38 my $global = \$GLOBALS{$name}; 39 my $ret; 40 41 if ($flavour =~ /ios32/) { 42 $ret = ".comm\t_$name,@args[1]\n"; 43 $ret .= ".non_lazy_symbol_pointer\n"; 44 $ret .= "$name:\n"; 45 $ret .= ".indirect_symbol\t_$name\n"; 46 $ret .= ".long\t0"; 47 $name = "_$name"; 48 } else { $ret = ".comm\t".join(',',@args); } 49 50 $$global = $name; 51 $ret; 52}; 53my $globl = sub { 54 my $name = shift; 55 my $global = \$GLOBALS{$name}; 56 my $ret; 57 58 SWITCH: for ($flavour) { 59 /ios/ && do { $name = "_$name"; 60 last; 61 }; 62 } 63 64 $ret = ".globl $name\n"; 65 # All symbols in assembly files are hidden. 66 $ret .= &$hidden($name); 67 $$global = $name; 68 $ret; 69}; 70my $global = $globl; 71my $extern = sub { 72 &$globl(@_); 73 return; # return nothing 74}; 75my $type = sub { 76 if ($flavour =~ /linux/) { ".type\t".join(',',@_); } 77 elsif ($flavour =~ /ios32/) { if (join(',',@_) =~ /(\w+),%function/) { 78 "#ifdef __thumb2__\n". 79 ".thumb_func $1\n". 80 "#endif"; 81 } 82 } 83 else { ""; } 84}; 85my $size = sub { 86 if ($flavour =~ /linux/) { ".size\t".join(',',@_); } 87 else { ""; } 88}; 89my $inst = sub { 90 if ($flavour =~ /linux/) { ".inst\t".join(',',@_); } 91 else { ".long\t".join(',',@_); } 92}; 93my $asciz = sub { 94 my $line = join(",",@_); 95 if ($line =~ /^"(.*)"$/) 96 { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } 97 else 98 { ""; } 99}; 100my $section = sub { 101 if ($flavour =~ /ios/) { 102 if ($_[0] eq ".rodata") { 103 return ".section\t__TEXT,__const"; 104 } 105 die "Unknown section name $_[0]"; 106 } else { 107 return ".section\t" . join(",", @_); 108 } 109}; 110 111sub range { 112 my ($r,$sfx,$start,$end) = @_; 113 114 join(",",map("$r$_$sfx",($start..$end))); 115} 116 117sub expand_line { 118 my $line = shift; 119 my @ret = (); 120 121 pos($line)=0; 122 123 while ($line =~ m/\G[^@\/\{\"]*/g) { 124 if ($line =~ m/\G(@|\/\/|$)/gc) { 125 last; 126 } 127 elsif ($line =~ m/\G\{/gc) { 128 my $saved_pos = pos($line); 129 $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e; 130 pos($line) = $saved_pos; 131 $line =~ m/\G[^\}]*\}/g; 132 } 133 elsif ($line =~ m/\G\"/gc) { 134 $line =~ m/\G[^\"]*\"/g; 135 } 136 } 137 138 $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge; 139 140 return $line; 141} 142 143print <<___; 144// This file is generated from a similarly-named Perl script in the BoringSSL 145// source tree. Do not edit by hand. 146 147#if !defined(__has_feature) 148#define __has_feature(x) 0 149#endif 150#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM) 151#define OPENSSL_NO_ASM 152#endif 153 154#if !defined(OPENSSL_NO_ASM) 155___ 156 157print "#if defined(__arm__)\n" if ($flavour eq "linux32"); 158print "#if defined(__aarch64__)\n" if ($flavour eq "linux64"); 159 160print "#if defined(BORINGSSL_PREFIX)\n"; 161print "#include <boringssl_prefix_symbols_asm.h>\n"; 162print "#endif\n"; 163 164while(my $line=<>) { 165 166 if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; } 167 168 $line =~ s|/\*.*\*/||; # get rid of C-style comments... 169 $line =~ s|^\s+||; # ... and skip white spaces in beginning... 170 $line =~ s|\s+$||; # ... and at the end 171 172 if ($flavour =~ /64/) { 173 my $copy = $line; 174 # Also remove line comments. 175 $copy =~ s|//.*||; 176 if ($copy =~ /\b[wx]18\b/) { 177 die "r18 is reserved by the platform and may not be used."; 178 } 179 } 180 181 { 182 $line =~ s|[\b\.]L(\w{2,})|L$1|g; # common denominator for Locallabel 183 $line =~ s|\bL(\w{2,})|\.L$1|g if ($dotinlocallabels); 184 } 185 186 { 187 $line =~ s|(^[\.\w]+)\:\s*||; 188 my $label = $1; 189 if ($label) { 190 printf "%s:",($GLOBALS{$label} or $label); 191 } 192 } 193 194 if ($line !~ m/^[#@]/) { 195 $line =~ s|^\s*(\.?)(\S+)\s*||; 196 my $c = $1; $c = "\t" if ($c eq ""); 197 my $mnemonic = $2; 198 my $opcode; 199 if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) { 200 $opcode = eval("\$$1_$2"); 201 } else { 202 $opcode = eval("\$$mnemonic"); 203 } 204 205 if ($flavour =~ /ios/) { 206 # Mach-O and ELF use different syntax for these relocations. Note 207 # that we require :pg_hi21: to be explicitly listed. It is normally 208 # optional with adrp instructions. 209 $line =~ s|:pg_hi21:(\w+)|\1\@PAGE|; 210 $line =~ s|:lo12:(\w+)|\1\@PAGEOFF|; 211 } else { 212 # Clang's integrated assembly does not support the optional 213 # :pg_hi21: markers, so erase them. 214 $line =~ s|:pg_hi21:||; 215 } 216 217 my $arg=expand_line($line); 218 219 if (ref($opcode) eq 'CODE') { 220 $line = &$opcode($arg); 221 } elsif ($mnemonic) { 222 $line = $c.$mnemonic; 223 $line.= "\t$arg" if ($arg ne ""); 224 } 225 } 226 227 print $line if ($line); 228 print "\n"; 229} 230 231print "#endif\n" if ($flavour eq "linux32" || $flavour eq "linux64"); 232print "#endif // !OPENSSL_NO_ASM\n"; 233 234# See https://www.airs.com/blog/archives/518. 235print ".section\t.note.GNU-stack,\"\",\%progbits\n" if ($flavour =~ /linux/); 236 237close STDOUT; 238