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 elsif ($flavour =~ /win64/) { ".arch\t".join(',',@_); } 26 else { ""; } 27}; 28my $fpu = sub { 29 if ($flavour =~ /linux/) { ".fpu\t".join(',',@_); } 30 else { ""; } 31}; 32my $hidden = sub { 33 if ($flavour =~ /ios/) { ".private_extern\t".join(',',@_); } 34 elsif ($flavour =~ /win64/) { ""; } 35 else { ".hidden\t".join(',',@_); } 36}; 37my $comm = sub { 38 my @args = split(/,\s*/,shift); 39 my $name = @args[0]; 40 my $global = \$GLOBALS{$name}; 41 my $ret; 42 43 if ($flavour =~ /ios32/) { 44 $ret = ".comm\t_$name,@args[1]\n"; 45 $ret .= ".non_lazy_symbol_pointer\n"; 46 $ret .= "$name:\n"; 47 $ret .= ".indirect_symbol\t_$name\n"; 48 $ret .= ".long\t0"; 49 $name = "_$name"; 50 } else { $ret = ".comm\t".join(',',@args); } 51 52 $$global = $name; 53 $ret; 54}; 55my $globl = sub { 56 my $name = shift; 57 my $global = \$GLOBALS{$name}; 58 my $ret; 59 60 SWITCH: for ($flavour) { 61 /ios/ && do { $name = "_$name"; 62 last; 63 }; 64 } 65 66 $ret = ".globl $name\n"; 67 # All symbols in assembly files are hidden. 68 $ret .= &$hidden($name); 69 $$global = $name; 70 $ret; 71}; 72my $global = $globl; 73my $extern = sub { 74 &$globl(@_); 75 return; # return nothing 76}; 77my $type = sub { 78 if ($flavour =~ /linux/) { ".type\t".join(',',@_); } 79 elsif ($flavour =~ /ios32/) { if (join(',',@_) =~ /(\w+),%function/) { 80 "#ifdef __thumb2__\n". 81 ".thumb_func $1\n". 82 "#endif"; 83 } 84 } 85 elsif ($flavour =~ /win64/) { if (join(',',@_) =~ /(\w+),%function/) { 86 # See https://sourceware.org/binutils/docs/as/Pseudo-Ops.html 87 # Per https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#coff-symbol-table, 88 # the type for functions is 0x20, or 32. 89 ".def $1\n". 90 " .type 32\n". 91 ".endef"; 92 } 93 } 94 else { ""; } 95}; 96my $size = sub { 97 if ($flavour =~ /linux/) { ".size\t".join(',',@_); } 98 else { ""; } 99}; 100my $inst = sub { 101 if ($flavour =~ /linux/) { ".inst\t".join(',',@_); } 102 else { ".long\t".join(',',@_); } 103}; 104my $asciz = sub { 105 my $line = join(",",@_); 106 if ($line =~ /^"(.*)"$/) 107 { ".byte " . join(",",unpack("C*",$1),0) . "\n.align 2"; } 108 else 109 { ""; } 110}; 111my $section = sub { 112 if ($flavour =~ /ios/) { 113 if ($_[0] eq ".rodata") { 114 return ".section\t__TEXT,__const"; 115 } 116 die "Unknown section name $_[0]"; 117 } else { 118 return ".section\t" . join(",", @_); 119 } 120}; 121 122sub range { 123 my ($r,$sfx,$start,$end) = @_; 124 125 join(",",map("$r$_$sfx",($start..$end))); 126} 127 128sub expand_line { 129 my $line = shift; 130 my @ret = (); 131 132 pos($line)=0; 133 134 while ($line =~ m/\G[^@\/\{\"]*/g) { 135 if ($line =~ m/\G(@|\/\/|$)/gc) { 136 last; 137 } 138 elsif ($line =~ m/\G\{/gc) { 139 my $saved_pos = pos($line); 140 $line =~ s/\G([rdqv])([0-9]+)([^\-]*)\-\1([0-9]+)\3/range($1,$3,$2,$4)/e; 141 pos($line) = $saved_pos; 142 $line =~ m/\G[^\}]*\}/g; 143 } 144 elsif ($line =~ m/\G\"/gc) { 145 $line =~ m/\G[^\"]*\"/g; 146 } 147 } 148 149 $line =~ s/\b(\w+)/$GLOBALS{$1} or $1/ge; 150 151 return $line; 152} 153 154my ($arch_defines, $target_defines); 155if ($flavour =~ /32/) { 156 $arch_defines = "defined(__ARMEL__)"; 157} elsif ($flavour =~ /64/) { 158 $arch_defines = "defined(__AARCH64EL__)"; 159} else { 160 die "unknown architecture: $flavour"; 161} 162if ($flavour =~ /linux/) { 163 # Although the flavour is specified as "linux", it is really used by all 164 # ELF platforms. 165 $target_defines = "defined(__ELF__)"; 166} elsif ($flavour =~ /ios/) { 167 # Although the flavour is specified as "ios", it is really used by all Apple 168 # platforms. 169 $target_defines = "defined(__APPLE__)"; 170} elsif ($flavour =~ /win/) { 171 $target_defines = "defined(_WIN32)"; 172} else { 173 die "unknown target: $flavour"; 174} 175 176print <<___; 177// This file is generated from a similarly-named Perl script in the BoringSSL 178// source tree. Do not edit by hand. 179 180#if !defined(__has_feature) 181#define __has_feature(x) 0 182#endif 183#if __has_feature(memory_sanitizer) && !defined(OPENSSL_NO_ASM) 184#define OPENSSL_NO_ASM 185#endif 186 187#if !defined(OPENSSL_NO_ASM) && $arch_defines && $target_defines 188___ 189 190print "#if defined(BORINGSSL_PREFIX)\n"; 191print "#include <boringssl_prefix_symbols_asm.h>\n"; 192print "#endif\n"; 193 194while(my $line=<>) { 195 196 if ($line =~ m/^\s*(#|@|\/\/)/) { print $line; next; } 197 198 $line =~ s|/\*.*\*/||; # get rid of C-style comments... 199 $line =~ s|^\s+||; # ... and skip white spaces in beginning... 200 $line =~ s|\s+$||; # ... and at the end 201 202 if ($flavour =~ /64/) { 203 my $copy = $line; 204 # Also remove line comments. 205 $copy =~ s|//.*||; 206 if ($copy =~ /\b[wx]18\b/) { 207 die "r18 is reserved by the platform and may not be used."; 208 } 209 } 210 211 { 212 $line =~ s|[\b\.]L(\w{2,})|L$1|g; # common denominator for Locallabel 213 $line =~ s|\bL(\w{2,})|\.L$1|g if ($dotinlocallabels); 214 } 215 216 { 217 $line =~ s|(^[\.\w]+)\:\s*||; 218 my $label = $1; 219 if ($label) { 220 printf "%s:",($GLOBALS{$label} or $label); 221 } 222 } 223 224 if ($line !~ m/^[#@]/) { 225 $line =~ s|^\s*(\.?)(\S+)\s*||; 226 my $c = $1; $c = "\t" if ($c eq ""); 227 my $mnemonic = $2; 228 my $opcode; 229 if ($mnemonic =~ m/([^\.]+)\.([^\.]+)/) { 230 $opcode = eval("\$$1_$2"); 231 } else { 232 $opcode = eval("\$$mnemonic"); 233 } 234 235 if ($flavour =~ /ios/) { 236 # Mach-O and ELF use different syntax for these relocations. Note 237 # that we require :pg_hi21: to be explicitly listed. It is normally 238 # optional with adrp instructions. 239 $line =~ s|:pg_hi21:(\w+)|\1\@PAGE|; 240 $line =~ s|:lo12:(\w+)|\1\@PAGEOFF|; 241 } else { 242 # Clang's integrated assembly does not support the optional 243 # :pg_hi21: markers, so erase them. 244 $line =~ s|:pg_hi21:||; 245 } 246 247 my $arg=expand_line($line); 248 249 if (ref($opcode) eq 'CODE') { 250 $line = &$opcode($arg); 251 } elsif ($mnemonic) { 252 $line = $c.$mnemonic; 253 $line.= "\t$arg" if ($arg ne ""); 254 } 255 } 256 257 print $line if ($line); 258 print "\n"; 259} 260 261print <<___; 262#endif // !OPENSSL_NO_ASM && $arch_defines && $target_defines 263#if defined(__ELF__) 264// See https://www.airs.com/blog/archives/518. 265.section .note.GNU-stack,"",\%progbits 266#endif 267___ 268 269close STDOUT or die "error closing STDOUT: $!"; 270