1# Create global symbol declarations, transfer vector, and 2# linker options files for PerlShr. 3# 4# Processes the output of makedef.pl. 5# 6# Input: 7# $cc_cmd - compiler command 8# $objsuffix - file type (including '.') used for object files. 9# $libperl - Perl object library. 10# $extnames - package names for static extensions (used to generate 11# linker options file entries for boot functions) 12# $rtlopt - name of options file specifying RTLs to which PerlShr.Exe 13# must be linked 14# 15# Output: 16# PerlShr_Attr.Opt - linker options file which specifies that global vars 17# be placed in NOSHR,WRT psects. Use when linking any object files 18# against PerlShr.Exe, since cc places global vars in SHR,WRT psects 19# by default. 20# PerlShr_Bld.Opt - declares universal symbols for PerlShr.Exe 21# 22# To do: 23# - figure out a good way to collect global vars in one psect, given that 24# we can't use globaldef because of gcc. 25# - then, check for existing files and preserve symbol and transfer vector 26# order for upward compatibility 27# - then, add GSMATCH to options file - but how do we insure that new 28# library has everything old one did 29# (i.e. /Define=DEBUGGING,EMBED,MULTIPLICITY)? 30# 31# Author: Charles Bailey bailey@newman.upenn.edu 32 33use strict; 34require 5.000; 35 36my $debug = $ENV{'GEN_SHRFLS_DEBUG'}; 37 38print "gen_shrfls.pl Rev. 8-Jul-2011\n" if $debug; 39 40if ($ARGV[0] eq '-f') { 41 open(INP,'<',$ARGV[1]) or die "Can't read input file $ARGV[1]: $!\n"; 42 print "Input taken from file $ARGV[1]\n" if $debug; 43 @ARGV = (); 44 while (<INP>) { 45 chomp; 46 push(@ARGV,split(/\|/,$_)); 47 } 48 close INP; 49 print "Read input data | ",join(' | ',@ARGV)," |\n" if $debug > 1; 50} 51 52my $cc_cmd = shift @ARGV; # no longer used to run the preprocessor 53 54print "Input \$cc_cmd: \\$cc_cmd\\\n" if $debug; 55my $docc = ($cc_cmd !~ /^~~/); 56print "\$docc = $docc\n" if $debug; 57 58my ( $use_threads, $use_mymalloc, $care_about_case, $shorten_symbols, 59 $debugging_enabled, $hide_mymalloc, $isgcc, $use_perlio, $dir ) 60 = ( 0, 0, 0, 0, 0, 0, 0, 0 ); 61 62if (-f 'perl.h') { $dir = '[]'; } 63elsif (-f '[-]perl.h') { $dir = '[-]'; } 64else { die "$0: Can't find perl.h\n"; } 65 66# Go see what is enabled in config.sh 67my $config = $dir . "config.sh"; 68open CONFIG, '<', $config; 69while(<CONFIG>) { 70 $use_threads++ if /usethreads='(define|yes|true|t|y|1)'/i; 71 $use_mymalloc++ if /usemymalloc='(define|yes|true|t|y|1)'/i; 72 $care_about_case++ if /d_vms_case_sensitive_symbols='(define|yes|true|t|y|1)'/i; 73 $shorten_symbols++ if /d_vms_shorten_long_symbols='(define|yes|true|t|y|1)'/i; 74 $debugging_enabled++ if /usedebugging_perl='(define|yes|true|t|y|1)'/i; 75 $hide_mymalloc++ if /embedmymalloc='(define|yes|true|t|y|1)'/i; 76 $isgcc++ if /gccversion='[^']/; 77 $use_perlio++ if /useperlio='(define|yes|true|t|y|1)'/i; 78} 79close CONFIG; 80 81# put quotes back onto defines - they were removed by DCL on the way in 82if (my ($prefix,$defines,$suffix) = 83 ($cc_cmd =~ m#(.*)/Define=(.*?)([/\s].*)#i)) { 84 $defines =~ s/^\((.*)\)$/$1/; 85 $debugging_enabled ||= $defines =~ /\bDEBUGGING\b/; 86 my @defines = split(/,/,$defines); 87 $cc_cmd = "$prefix/Define=(" . join(',',grep($_ = "\"$_\"",@defines)) 88 . ')' . $suffix; 89} 90print "Filtered \$cc_cmd: \\$cc_cmd\\\n" if $debug; 91 92# check for gcc - if present, we'll need to use MACRO hack to 93# define global symbols for shared variables 94 95print "\$isgcc: $isgcc\n" if $debug; 96print "\$debugging_enabled: $debugging_enabled\n" if $debug; 97 98my $objsuffix = shift @ARGV; 99print "\$objsuffix: \\$objsuffix\\\n" if $debug; 100my $dbgprefix = shift @ARGV; 101print "\$dbgprefix: \\$dbgprefix\\\n" if $debug; 102my $olbsuffix = shift @ARGV; 103print "\$olbsuffix: \\$olbsuffix\\\n" if $debug; 104my $libperl = "${dbgprefix}libperl$olbsuffix"; 105my $extnames = shift @ARGV; 106print "\$extnames: \\$extnames\\\n" if $debug; 107my $rtlopt = shift @ARGV; 108print "\$rtlopt: \\$rtlopt\\\n" if $debug; 109 110my (%vars, %fcns); 111 112open my $makedefs, '<', $dir . 'makedef.lis' or die "Unable to open makedef.lis: $!"; 113 114while (my $line = <$makedefs>) { 115 chomp $line; 116 $line = shorten_symbol($line, $care_about_case) if $shorten_symbols; 117 # makedef.pl loses distinction between vars and funcs, so 118 # use the start of the name to guess and add specific 119 # exceptions when we know about them. 120 if ($line =~ m/^(PL_|MallocCfg)/ 121 || $line eq 'PerlIO_perlio' 122 || $line eq 'PerlIO_pending') { 123 $vars{$line}++; 124 } 125 else { 126 $fcns{$line}++; 127 } 128} 129 130if ($debugging_enabled and $isgcc) { $vars{'colors'}++ } 131foreach (split /\s+/, $extnames) { 132 my($pkgname) = $_; 133 $pkgname =~ s/::/__/g; 134 $fcns{"boot_$pkgname"}++; 135 print "Adding boot_$pkgname to \%fcns (for extension $_)\n" if $debug; 136} 137 138# Eventually, we'll check against existing copies here, so we can add new 139# symbols to an existing options file in an upwardly-compatible manner. 140 141my $marord = 1; 142open(OPTBLD,'>', "${dir}${dbgprefix}perlshr_bld.opt") 143 or die "$0: Can't write to ${dir}${dbgprefix}perlshr_bld.opt: $!\n"; 144 145unless ($isgcc) { 146 print OPTBLD "PSECT_ATTR=LIB\$INITIALIZE,GBL,NOEXE,NOWRT,NOSHR,LONG\n"; 147} 148print OPTBLD "case_sensitive=yes\n" if $care_about_case; 149my $count = 0; 150foreach my $var (sort (keys %vars)) { 151 print OPTBLD "SYMBOL_VECTOR=($var=DATA)\n"; 152} 153 154foreach my $func (sort keys %fcns) { 155 print OPTBLD "SYMBOL_VECTOR=($func=PROCEDURE)\n"; 156} 157 158open(OPTATTR, '>', "${dir}perlshr_attr.opt") 159 or die "$0: Can't write to ${dir}perlshr_attr.opt: $!\n"; 160if ($isgcc) { 161# TODO -- lost ability to distinguish constant vars from others when 162# we switched to using makedef.pl for input. 163# foreach my $var (sort keys %cvars) { 164# print OPTATTR "PSECT_ATTR=${var},PIC,OVR,RD,NOEXE,NOWRT,SHR\n"; 165# } 166 foreach my $var (sort keys %vars) { 167 print OPTATTR "PSECT_ATTR=${var},PIC,OVR,RD,NOEXE,WRT,NOSHR\n"; 168 } 169} 170else { 171 print OPTATTR "! No additional linker directives are needed when using DECC\n"; 172} 173close OPTATTR; 174 175my $incstr = 'PERL,GLOBALS'; 176my (@symfiles, $drvrname); 177 178# Initial hack to permit building of compatible shareable images for a 179# given version of Perl. 180if ($ENV{PERLSHR_USE_GSMATCH}) { 181 if ($ENV{PERLSHR_USE_GSMATCH} eq 'INCLUDE_COMPILE_OPTIONS') { 182 # Build up a major ID. Since on Alpha it can only be 8 bits, we encode 183 # the version number in the top 5 bits and use the bottom 3 for build 184 # options most likely to cause incompatibilities. Breaks at Perl 5.32. 185 my ($ver, $sub) = $] =~ /\.(\d\d\d)(\d\d\d)/; 186 $ver += 0; $sub += 0; 187 my $gsmatch = ($ver % 2 == 1) ? "EQUAL" : "LEQUAL"; # Force an equal match for 188 # dev, but be more forgiving 189 # for releases 190 191 $ver <<= 3; 192 $ver += 1 if $debugging_enabled; # If DEBUGGING is set 193 $ver += 2 if $use_threads; # if we're threaded 194 $ver += 4 if $use_mymalloc; # if we're using perl's malloc 195 print OPTBLD "GSMATCH=$gsmatch,$ver,$sub\n"; 196 } 197 else { 198 my $major = int($] * 1000) & 0xFF; # range 0..255 199 my $minor = int(($] * 1000 - $major) * 100 + 0.5) & 0xFF; # range 0..255 200 print OPTBLD "GSMATCH=LEQUAL,$major,$minor\n"; 201 } 202} 203elsif (@symfiles) { $incstr .= ',' . join(',',@symfiles); } 204# Include object modules and RTLs in options file 205# Linker wants /Include and /Library on different lines 206print OPTBLD "$libperl/Include=($incstr)\n"; 207print OPTBLD "$libperl/Library\n"; 208open(RTLOPT,'<',$rtlopt) or die "$0: Can't read options file $rtlopt: $!\n"; 209while (<RTLOPT>) { print OPTBLD; } 210close RTLOPT; 211close OPTBLD; 212 213 214# Symbol shortening Copyright (c) 2012 Craig A. Berry 215# 216# Released under the same terms as Perl itself. 217# 218# This code provides shortening of long symbols (> 31 characters) using the 219# same mechanism as the OpenVMS C compiler. The basic procedure is to compute 220# an AUTODIN II checksum of the entire symbol, encode the checksum in base32, 221# and glue together a shortened symbol from the first 23 characters of the 222# original symbol plus the encoded checksum appended. The output format is 223# the same used in the name mangler database, stored by default in 224# [.CXX_REPOSITORY]CXX$DEMANGLER_DB. 225 226sub crc32 { 227 use constant autodin_ii_table => [ 228 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 229 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 230 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 231 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 232 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 233 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 234 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 235 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 236 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 237 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 238 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 239 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 240 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 241 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 242 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 243 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 244 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 245 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 246 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 247 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 248 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 249 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 250 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 251 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 252 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 253 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 254 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 255 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 256 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 257 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 258 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 259 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 260 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 261 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 262 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 263 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 264 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 265 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 266 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 267 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 268 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 269 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 270 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d, 271 ]; 272 273 my $input_string = shift; 274 my $crc = 0xFFFFFFFF; 275 276 for my $byte (unpack 'C*', $input_string) { 277 $crc = ($crc >> 8) ^ autodin_ii_table->[($crc ^ $byte) & 0xff]; 278 } 279 return ~$crc; 280} 281 282sub base32 { 283 my $input = shift; 284 my $output = ''; 285 use constant base32hex_table => [ 286 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 287 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 288 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 289 'u', 'v' 290 ]; 291 292 # Grab lowest 5 bits and look up conversion in table. Lather, rinse, 293 # repeat for a total of 7, 5-bit chunks to accommodate 32 bits of input. 294 295 for (0..6) { 296 $output = base32hex_table->[$input & 0x1f] . $output; 297 $input >>= 5; # position to look at next 5 298 } 299 $output .= '$'; # It's DEC, so use '$' not '=' to pad. 300 301 return $output; 302} 303 304sub shorten_symbol { 305 my $input_symbol = shift; 306 my $as_is_flag = shift; 307 my $symbol = $input_symbol; 308 309 return $symbol unless length($input_symbol) > 31; 310 311 $symbol = uc($symbol) unless $as_is_flag; 312 my $crc = crc32($symbol); 313 $crc = ~$crc; # Compiler uses non-inverted form. 314 my $b32 = base32($crc); 315 $b32 = uc($b32) unless $as_is_flag; 316 317 return substr($symbol, 0, 23) . $b32; 318} 319 320__END__ 321 322