imgtools/romtools/rombuild/checkstubs.pl
changeset 2 39c28ec933dd
equal deleted inserted replaced
1:820b22e13ff1 2:39c28ec933dd
       
     1 #
       
     2 # Copyright (c) 2004-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 # Perl script to check that import stubs go to the right place
       
    16 #
       
    17 
       
    18 my $symbolfile="ba_001.engbuild.symbol";
       
    19 my $imagefile="ba_001.engbuild.img";
       
    20 my $imageoffset=0;	# will be read from the image header
       
    21 
       
    22 die "Usage: checkstubs [imagefile]\n" if (@ARGV>1);
       
    23 if (@ARGV==1)
       
    24 	{
       
    25 	$imagefile = @ARGV[0];
       
    26 	$symbolfile = $imagefile;
       
    27 	$symbolfile =~ s/img$/symbol/i;
       
    28 	}
       
    29 
       
    30 # 1. Read in the SYMBOL information
       
    31 #
       
    32 # From    \epoc32\release\ARM4\urel\netdial.agt
       
    33 # 50989f5c    00c0    CImap4Utils::SendLogMessageL(int, TRequestStatus &)
       
    34 # 5098a01c    000c    stub UserSvr::DllGlobalAlloc(int, int)
       
    35 
       
    36 my %stubs;		# stub names, by address
       
    37 my %funcs;		# function names, by address
       
    38 my %knownfuncs;	# function names which are reported in symbol file
       
    39 my $line;
       
    40 
       
    41 open SYMBOL, "<$symbolfile" or die "Cannot open $symbolfile";
       
    42 while ($line=<SYMBOL>)
       
    43 	{
       
    44 	if ($line =~ /^([0-9a-f]{8})\s+[0-9a-f]+\s+(.*)$/i)
       
    45 		{
       
    46 		my $address = hex($1);
       
    47 		my $name = $2;
       
    48 
       
    49 		$funcs{$address} = $name;
       
    50 		$knownfuncs{$name} = 1;
       
    51 		if ($name =~/^stub (.*)$/)
       
    52 			{
       
    53 			$stubs{$address} = $1;	# lots of stubs, but only one address!
       
    54 			}
       
    55 		}
       
    56 	}
       
    57 close SYMBOL;
       
    58 
       
    59 # 2. Understand the ROM structure
       
    60 #
       
    61 
       
    62 open IMAGE, "<$imagefile" or die "Cannot open $imagefile";
       
    63 binmode IMAGE;
       
    64 
       
    65 my $stubaddress;
       
    66 my $stubdata;
       
    67 my $stubcount=0;
       
    68 my $errors=0;
       
    69 my $uncheckable=0;
       
    70 
       
    71 read IMAGE, $stubdata, 20;
       
    72 if ($stubdata =~ /^EPOC....ROM/)
       
    73 	{
       
    74 	$imageoffset -= 256;	# compensate for REPRO header
       
    75 	}
       
    76 
       
    77 # Read the image header to determine ROM linear address
       
    78 
       
    79 sub read_imageword
       
    80     {
       
    81     my $imagedata;
       
    82 	read IMAGE, $imagedata, 4;
       
    83     return unpack "V", $imagedata;
       
    84     }
       
    85 
       
    86 seek(IMAGE, 0x8c-$imageoffset, 0);
       
    87 my $romlinearbase = read_imageword();
       
    88 my $romsize = read_imageword();
       
    89 $imageoffset += $romlinearbase;
       
    90 
       
    91 my %areas;
       
    92 my %area_offsets;
       
    93 $areas{$romlinearbase} = $romlinearbase+$romsize;
       
    94 $area_offsets{$romlinearbase} = $imageoffset;
       
    95 
       
    96 # Check for the extension ROM
       
    97 
       
    98 if (seek(IMAGE, $romlinearbase+$romsize+0xC-$imageoffset,0))
       
    99 	{
       
   100 	my $extensionlinearbase = read_imageword();
       
   101 	my $extensionsize = read_imageword();
       
   102 
       
   103 	$areas{$extensionlinearbase} = $extensionlinearbase+$extensionsize;
       
   104 	$area_offsets{$extensionlinearbase} = 
       
   105 		$imageoffset+($extensionlinearbase - $romlinearbase -$romsize);
       
   106 	}
       
   107 
       
   108 sub image_seek
       
   109 	{
       
   110 	my ($runaddress) = @_;
       
   111 	my $offset = 0;
       
   112 
       
   113 	# Scan list of area mappings to determine correct offset
       
   114 	my $areabase;
       
   115 	foreach $areabase (keys %areas)
       
   116 		{
       
   117 		if ($areabase <= $runaddress && $areas{$areabase} > $runaddress)
       
   118 			{
       
   119 			$offset = $area_offsets{$areabase};
       
   120 			last;
       
   121 			}
       
   122 		}
       
   123 	if ($offset==0)
       
   124 		{
       
   125 		printf "Can't find area for address 0x%x\n", $runaddress, $runaddress-$imageoffset;
       
   126 		$errors++;
       
   127 		return 0;
       
   128 		}
       
   129 	#
       
   130 	if (!seek(IMAGE, $runaddress-$offset, 0))
       
   131 		{
       
   132 		printf "Can't seek to address 0x%x => offset 0x%x\n", $runaddress, $runaddress-$imageoffset;
       
   133 		$errors++;
       
   134 		return 0;
       
   135 		}
       
   136 	return 1;
       
   137 	}
       
   138 
       
   139 # Read the area relocation information (if any)
       
   140 
       
   141 image_seek($romlinearbase+0xd4);
       
   142 my $areaptr = read_imageword();
       
   143 if ($areaptr != 0)
       
   144 	{
       
   145 	image_seek($areaptr);
       
   146 	my $areasize=0;
       
   147 	while ($areasize=read_imageword())
       
   148 		{
       
   149 		my $srcbase=read_imageword();
       
   150 		my $areabase=read_imageword();
       
   151 		$areas{$areabase} = $areabase+$areasize;
       
   152 		$area_offsets{$areabase} = $imageoffset+($areabase-$srcbase);
       
   153 		}
       
   154 	}
       
   155 
       
   156 # 3. Scan the stubs
       
   157 #
       
   158 
       
   159 foreach $stubaddress (sort keys %stubs)
       
   160 	{
       
   161 	my $stub = $stubs{$stubaddress};
       
   162 	$stubcount++;
       
   163 	if (!image_seek($stubaddress))
       
   164 		{
       
   165 		printf "Can't seek to %s at x%x\n", $stub, $stubaddress;
       
   166 		$errors++;
       
   167 		next;
       
   168 		}
       
   169 	read IMAGE, $stubdata, 20;
       
   170 
       
   171 	my @arm_instructions = (unpack "V4", $stubdata);
       
   172 	my @thumb_instructions = (unpack "v6", $stubdata);
       
   173 
       
   174 	my $address = $stubaddress;
       
   175 	my $indirections =-1;
       
   176 	my $finalbx = 1;
       
   177 
       
   178 	if (@arm_instructions[0] == 0xe59fc000 &&
       
   179 		@arm_instructions[1] == 0xe59cf000)
       
   180 		{
       
   181 		# arm4 stub
       
   182 		$indirections=2;
       
   183 		$address+=8;
       
   184 		$finalbx = 0;
       
   185 		}
       
   186 	if (@arm_instructions[0] == 0xe59fc004 &&
       
   187 		@arm_instructions[1] == 0xe59cc000 &&
       
   188 		@arm_instructions[2] == 0xe12fff1c)
       
   189 		{
       
   190 		# armi stub
       
   191 		$indirections=2;
       
   192 		$address+=12;
       
   193 		}
       
   194 	if (@arm_instructions[0] == 0xe59fc004 &&
       
   195 		@arm_instructions[1] == 0xe12fff1c)
       
   196 		{
       
   197 		# fast armi stub
       
   198 		$indirections=1;
       
   199 		$address+=12;
       
   200 		}
       
   201 	if (@thumb_instructions[0] == 0xb440 &&
       
   202 		@thumb_instructions[1] == 0x4e02 &&
       
   203 		@thumb_instructions[2] == 0x6836 &&
       
   204 		@thumb_instructions[3] == 0x46b4 &&
       
   205 		@thumb_instructions[4] == 0xbc40 &&
       
   206 		@thumb_instructions[5] == 0x4760)
       
   207 		{
       
   208 		# thumb stub
       
   209 		$indirections=2;
       
   210 		$address+=12;
       
   211 		}
       
   212 	if (@thumb_instructions[0] == 0xb440 &&
       
   213 		@thumb_instructions[1] == 0x4e02 &&
       
   214 		@thumb_instructions[2] == 0x46b4 &&
       
   215 		@thumb_instructions[3] == 0xbc40 &&
       
   216 		@thumb_instructions[4] == 0x4760)
       
   217 		{
       
   218 		# fast thumb stub
       
   219 		$indirections=1;
       
   220 		$address+=12;
       
   221 		}
       
   222 	if (@thumb_instructions[0] == 0x4b01 &&
       
   223 		@thumb_instructions[1] == 0x681b &&
       
   224 		@thumb_instructions[2] == 0x4718)
       
   225 		{
       
   226 		# thumb r3unused stub
       
   227 		$indirections=2;
       
   228 		$address+=8;
       
   229 		}
       
   230 	if (@thumb_instructions[0] == 0x4b01 &&
       
   231 		@thumb_instructions[1] == 0x4718)
       
   232 		{
       
   233 		# fast thumb r3unused stub
       
   234 		$indirections=1;
       
   235 		$address+=8;
       
   236 		}
       
   237 
       
   238 	if ($indirections < 0)
       
   239 		{
       
   240 		printf "At %08x unrecognised stub %s = %08x %08x %08x %08x\n", $stubaddress, $stub,
       
   241 			@arm_instructions[0], @arm_instructions[1], @arm_instructions[2], @arm_instructions[3];
       
   242 		$errors++;
       
   243 		next;
       
   244 		}
       
   245 
       
   246 	my $indirection_count = $indirections;
       
   247 	while ($indirection_count > 0)
       
   248 		{
       
   249 		if (!image_seek($address))
       
   250 			{
       
   251 			printf "Failed to follow %s to address 0x%x\n", $stub, $address;
       
   252 			$errors++;
       
   253 			last;
       
   254 			}
       
   255 		my $data;
       
   256 		read IMAGE, $data, 4;
       
   257 		$address = unpack "V", $data;
       
   258 		$indirection_count -= 1;
       
   259 		}
       
   260 	next if ($indirection_count != 0);
       
   261 
       
   262 	if ($finalbx)
       
   263 		{
       
   264 		$address &= 0xfffffffe;	# clear THUMB mode indicator
       
   265 		}
       
   266 
       
   267 	if (!defined($funcs{$address}))
       
   268 		{
       
   269 		if (!defined($knownfuncs{$stub}))
       
   270 			{
       
   271 			# we don't have a map file for the provider of this function anyway
       
   272 			$uncheckable++;
       
   273 			next;
       
   274 			}
       
   275 		printf "At %08x stub %s points to %08x, which is not a known function\n", $stubaddress, $stub, $address;
       
   276 		$errors++;
       
   277 		next;
       
   278 		}
       
   279 	if ($funcs{$address} ne $stub)
       
   280 		{
       
   281 		printf "At %08x stub %s points to %08x, which is %s\n", $stubaddress, $stub, $address, $funcs{$address};
       
   282 		$errors++;
       
   283 		next;
       
   284 		}
       
   285 	# Hurrah - it goes to the right place...
       
   286 	}
       
   287 close IMAGE;
       
   288 
       
   289 print "Checked $symbolfile and $imagefile\n";
       
   290 if ($errors==0 && $uncheckable==0)
       
   291 	{
       
   292 	print "All $stubcount stubs passed\n";
       
   293 	}
       
   294 else
       
   295 	{
       
   296 	print "Tested $stubcount stubs, $uncheckable couldn't be verified, found $errors errors\n";
       
   297 	}
       
   298 exit ($errors);