bintools/elftools/def2dll.pl
changeset 0 044383f39525
child 606 30b30f9da0b7
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 #
       
     2 # Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 # All rights reserved.
       
     4 # This component and the accompanying materials are made available
       
     5 # under the terms of the License "Eclipse Public License v1.0"
       
     6 # which accompanies this distribution, and is available
       
     7 # at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 #
       
     9 # Initial Contributors:
       
    10 # Nokia Corporation - initial contribution.
       
    11 #
       
    12 # Contributors:
       
    13 #
       
    14 # Description: 
       
    15 #
       
    16 
       
    17 use strict;
       
    18 use FindBin;		# for FindBin::Bin
       
    19 use Getopt::Long;
       
    20 use Cwd;
       
    21 
       
    22 my $PerlLibPath;    # fully qualified pathname of the directory containing our Perl modules
       
    23 
       
    24 BEGIN {
       
    25 # check user has a version of perl that will cope
       
    26 	require 5.005_03;
       
    27 # establish the path to the Perl libraries: currently the same directory as this script
       
    28 	$PerlLibPath = $FindBin::Bin;	# X:/epoc32/tools
       
    29 	if ($^O eq "MSWin32")
       
    30 	{
       
    31 		$PerlLibPath =~ s/\//\\/g;	# X:\epoc32\tools
       
    32 		$PerlLibPath .= "\\";
       
    33 	}	
       
    34 }
       
    35 
       
    36 use lib $PerlLibPath;
       
    37 use Defutl;
       
    38 
       
    39 my %opts = ();
       
    40 
       
    41 my $result = GetOptions(\%opts,
       
    42 						"path:s",
       
    43 						"bldpath:s",
       
    44 						"deffile:s",
       
    45 						"linkAs:s",
       
    46 						"import:s",
       
    47 						"export:s",
       
    48 						"absent:s",
       
    49 						"inter",
       
    50 						"sym_name_lkup"
       
    51 						);
       
    52 
       
    53 my $gPath = $opts{"path"}; # 0
       
    54 my $gBldPath = $opts{"bldpath"}; # 0
       
    55 my $compName = $opts{"import"}; # 1
       
    56 my $gDefFile = $opts{"deffile"}; # 2
       
    57 my $gDllName = $opts{"linkAs"};  # 3
       
    58 my $gExpFile = $opts{"export"};
       
    59 my $gLibFile = "$compName.lib" if $compName;
       
    60 my $gSymbolNameLookup = $opts{"sym_name_lkup"};
       
    61 
       
    62 my $oP = '--';
       
    63 
       
    64 my $floatingpointmodel = "${oP}fpu softvfp";
       
    65 my $interworkingp = $opts{"inter"};
       
    66 my $interworking = "${oP}apcs /nointer";
       
    67 $interworking = "${oP}apcs /inter" if ($interworkingp);
       
    68 
       
    69 my @objectFiles;
       
    70 
       
    71 &main;
       
    72 
       
    73 my @DefDataStruct;
       
    74 
       
    75 sub main ()
       
    76 {
       
    77        unless($gDefFile)
       
    78        {
       
    79                usage();
       
    80        }
       
    81 	my $FrzExportsOn=0;
       
    82 	eval { &Def_ReadFileL(\@DefDataStruct, $gDefFile, $FrzExportsOn); };
       
    83 	die $@ if $@;
       
    84 
       
    85     &parseDefFile(\@DefDataStruct, $opts{absent}, $gDefFile);
       
    86     &genExpFile($gPath, $gBldPath, $gExpFile) if $gExpFile;
       
    87     &genLibFile($gPath, $gBldPath, $gLibFile, $gDllName) if $gLibFile;
       
    88 }
       
    89 
       
    90 # Usage subroutine
       
    91 sub usage( )
       
    92 {
       
    93         print "\n";
       
    94         print "DEF2DLL -Creates binary objects used to implement the Symbian OS DLL model\n";
       
    95         print "\n";
       
    96         print "Usage: def2dll --deffile=<file> [--path=<dir>] [--bldpath=<dir>] [--import=<file>]  [--linkas=<file>] [--inter] [--export=<file>] [--sym_name_lkup]\n";
       
    97 
       
    98         print "\nOptions:\n";
       
    99 	print "\t--deffile=<file>   	 	: def file to be converted\n";
       
   100         print "\t--path =<direcotry>		: destination path\n";
       
   101         print "\t--bldpath=<direcotry>		: build path for dll\n";
       
   102         print "\t--import=<file>			: import from file name\n";
       
   103         print "\t--linkas=<file>     		: linkas to file name specified\n";
       
   104         print "\t--inter                 	: enables interworking on ARM and THUMB\n";
       
   105         print "\t--export=<file>			: export to filename\n";
       
   106         print "\t--sym_name_lkup         	: symbol name ordinal number lookupç\n";
       
   107         print "\n";
       
   108         exit 1;
       
   109 }
       
   110 
       
   111 my %symbols = ();
       
   112 my %symbolIndexMap = ();
       
   113 my $exports = 0;
       
   114 
       
   115 sub parseDefFile ($$$)
       
   116 {
       
   117     my ($defStructRef, $AbsentSubst, $defFile) = @_;
       
   118 	my $Ref;
       
   119 	foreach $Ref (@$defStructRef) {
       
   120 		next if (!$Ref);
       
   121 		next if (!defined ($$Ref{Ordinal}));
       
   122 		my $symbol = $$Ref{Name};
       
   123 		my $index = $$Ref{Ordinal};
       
   124 		my $rest = $$Ref{Comment};
       
   125 		my $symbolType = 'CODE';
       
   126 		if ($$Ref{Data} || ($symbol =~ /^(_ZTV|_ZTI|_ZTT)/)){
       
   127 			$symbolType = 'DATA';
       
   128 		}
       
   129 		else {
       
   130 			$exports = 1;
       
   131 		}
       
   132 		if ($symbols{$symbol} and !$$Ref{Absent}) {
       
   133 			warn "DEF2DLL - WARNING: $symbol duplicated in $defFile\n";
       
   134 		} else {
       
   135 			if ($$Ref{Absent}) {
       
   136 				$symbolIndexMap{$index} = $AbsentSubst;
       
   137 			} else {
       
   138 				$symbols{$symbol} = $symbolType;
       
   139 				$symbolIndexMap{$index} = $symbol;
       
   140 			}
       
   141 		}
       
   142     }
       
   143 }
       
   144 
       
   145 sub genExpFile ($$$)
       
   146 {
       
   147     my ($path, $bldpath, $expFile) = @_;
       
   148     my $numkeys = keys %symbolIndexMap;
       
   149     my $failed = 0;
       
   150 
       
   151     open EXPFILE, ">$path\\$expFile.s" or
       
   152 		die "Error: can't create $path\\$expFile.s\n";
       
   153 
       
   154     print EXPFILE "\tEXPORT __DLL_Export_Table__\n\n";
       
   155     print EXPFILE "\tEXPORT |DLL\#\#ExportTable|\n\n";
       
   156     print EXPFILE "\tEXPORT |DLL\#\#ExportTableSize|\n\n";
       
   157     print EXPFILE "\tAREA ExportTable, CODE\n";
       
   158 
       
   159 
       
   160     print EXPFILE "__DLL_Export_Table__\n";
       
   161 	if ($interworkingp) {
       
   162 	  print EXPFILE "\tBX lr\n";
       
   163 	} else {
       
   164 	  print EXPFILE "\tMOV pc, lr\n";
       
   165 	}
       
   166 
       
   167     print EXPFILE "|DLL\#\#ExportTableSize|\n";
       
   168     printf EXPFILE "\tDCD %d\n", $numkeys;
       
   169 	if($gSymbolNameLookup) {
       
   170 		print EXPFILE "\tDCD 0 \n";# This is the 0th ordinal for elftran to fill in.
       
   171 	}
       
   172     print EXPFILE "|DLL\#\#ExportTable|\n";
       
   173 
       
   174     my @orderedSyms;
       
   175     my $maxIndex = 0;
       
   176     my $index;
       
   177     foreach $index (keys %symbolIndexMap) {
       
   178 		$maxIndex = $index if $index > $maxIndex;
       
   179 		$orderedSyms[$index] = $symbolIndexMap{$index};
       
   180     }
       
   181 
       
   182     print EXPFILE "\tPRESERVE8\n\n";
       
   183     my $n;
       
   184     for ($n = 1; $n <= $maxIndex ; $n++) {
       
   185 		my $entry = $orderedSyms[$n];
       
   186 		if ($entry) {
       
   187 			print EXPFILE "\tIMPORT $entry\n";
       
   188 			print EXPFILE "\tDCD $entry \t; @ $n\n";
       
   189 		} else {
       
   190 			warn "WARNING: missing entry at index $n\n";
       
   191 			print EXPFILE "\tDCD 0 ; missing symbol\n";
       
   192 		}
       
   193     }
       
   194 
       
   195 
       
   196     # create a .directive section
       
   197     print EXPFILE "\n\n\tAREA |.directive|, READONLY, NOALLOC\n";
       
   198     # Mark the section as armlink edit commands
       
   199     print EXPFILE "\tDCB  \"#<SYMEDIT>#\\n\"\n"; 
       
   200     # mark the imported symbol for 'dynamic' export
       
   201     print EXPFILE "\tDCB  \"EXPORT DLL##ExportTable\\n\"\n";
       
   202     print EXPFILE "\tDCB  \"EXPORT DLL##ExportTableSize\\n\"\n";
       
   203 
       
   204     print EXPFILE "\tEND";
       
   205     close EXPFILE;
       
   206 
       
   207     $failed = system "armasm $floatingpointmodel $interworking -o $path\\$expFile.exp $path\\$expFile.s";
       
   208     unlink ("$path\\$expFile.s") unless $failed;
       
   209     die "Error: cant create $path\\$expFile.exp\n" if $failed;
       
   210 }
       
   211 
       
   212 my %DataSymbols = ();
       
   213 
       
   214 sub genVtblExportFile($$)
       
   215 {
       
   216     my ($bldpath, $dllName) = @_;
       
   217     my $FileName = "VtblExports";
       
   218 
       
   219     open VTBLFILE, ">$bldpath\\$FileName.s" or
       
   220 		die "Error: can't create $bldpath\\$FileName.s\n";
       
   221 
       
   222     print VTBLFILE "\tAREA |.directive|, NOALLOC, READONLY, ALIGN=2\n";
       
   223     printf VTBLFILE "\tDCB \"\#\<SYMEDIT\>\#\\n\"\n";
       
   224 
       
   225     my $symbol;
       
   226     foreach $symbol (sort keys %DataSymbols) {
       
   227 		my $index = $DataSymbols{$symbol};
       
   228 		
       
   229 		$symbol =~ s/^"(.*)"$/$1/;	# remove enclosing quotes
       
   230 		printf VTBLFILE "\tDCB \"IMPORT \#\<DLL\>$dllName\#\<\\\\DLL\>%x AS $symbol \\n\"\n", $index;
       
   231     }
       
   232 #    printf VTBLFILE "\tDCB \"\#\<\\\\VTBLSYMS\>\#\\n\"\n";
       
   233     print VTBLFILE "\tEND";
       
   234     close VTBLFILE;
       
   235 
       
   236     my $failed = system "armasm $floatingpointmodel $interworking -o $bldpath\\$FileName.o $bldpath\\$FileName.s";
       
   237     unlink ("$bldpath\\$FileName.s");
       
   238     die "Error: cant create $bldpath\\$FileName.o\n" if $failed;
       
   239     push @objectFiles, "$bldpath\\$FileName.o";
       
   240 }
       
   241 
       
   242 sub genLibFile ($$$$)
       
   243 {
       
   244     my ($path, $bldpath, $libFile, $dllName) = @_;
       
   245     my $tempFileName = "$bldpath\\$compName";
       
   246     my $viaFileName = sprintf("$bldpath\\_t%x_via_.txt", time);
       
   247     my $keyz = keys %symbolIndexMap;
       
   248     my $failed = 0;
       
   249     my $key;
       
   250 
       
   251     if ($keyz > 0) {
       
   252 		open STUBGEN, "|$ENV{'EPOCROOT'}/epoc32/tools/genstubs" if $exports;
       
   253 		foreach $key (sort keys %symbolIndexMap) {
       
   254 			my $symbol = $symbolIndexMap{$key};
       
   255 			my $stubFileName = "$tempFileName-$key";
       
   256 			if ( $symbols{$symbol} eq 'DATA') {
       
   257 				$DataSymbols{$symbol} = $key;
       
   258 			} else {
       
   259 				printf STUBGEN "$stubFileName.o $symbol #<DLL>$dllName#<\\DLL>%x\n", $key;
       
   260 				push @objectFiles, "$stubFileName.o";
       
   261 			}
       
   262 		}
       
   263 		genVtblExportFile($bldpath, $dllName);
       
   264     } else {
       
   265 		# create dummy stub so armar creates a .lib for us
       
   266 		open STUBGEN, "|$ENV{'EPOCROOT'}/epoc32/tools/genstubs";
       
   267 		print STUBGEN "$tempFileName-stub.o $tempFileName##stub $dllName##dummy\n";
       
   268 		push @objectFiles, "$tempFileName-stub.o";
       
   269     }
       
   270     close STUBGEN;
       
   271 
       
   272     open VIAFILE, ">$viaFileName" or
       
   273 		die "Error: can't create VIA fie $viaFileName\n";
       
   274 
       
   275     print VIAFILE "${oP}create \"$path\\$libFile\"\n";
       
   276     my $objectFile;
       
   277     foreach $objectFile (@objectFiles) {
       
   278 		print VIAFILE "\"$objectFile\"\n";
       
   279     }
       
   280     close VIAFILE;
       
   281 
       
   282     $failed = system( "armar ${oP}via $viaFileName");
       
   283     push @objectFiles, $viaFileName;
       
   284     unlink @objectFiles;
       
   285     die "Error: can't create $path\\$libFile\n" if $failed;
       
   286 }
       
   287 
       
   288 __END__
       
   289