rjw | 6c1fd8f | 2022-11-30 14:33:01 +0800 | [diff] [blame] | 1 | #!/usr/bin/perl
|
| 2 | #
|
| 3 | # Copyright Statement:
|
| 4 | # --------------------
|
| 5 | # This software is protected by Copyright and the information contained
|
| 6 | # herein is confidential. The software may not be copied and the information
|
| 7 | # contained herein may not be used or disclosed except with the written
|
| 8 | # permission of MediaTek Inc. (C) 2006
|
| 9 | #
|
| 10 | # BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
|
| 11 | # THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
|
| 12 | # RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
|
| 13 | # AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
|
| 14 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
|
| 15 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
|
| 16 | # NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
|
| 17 | # SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
|
| 18 | # SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
|
| 19 | # THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
|
| 20 | # NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
|
| 21 | # SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
|
| 22 | #
|
| 23 | # BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
|
| 24 | # LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
|
| 25 | # AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
|
| 26 | # OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
|
| 27 | # MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
|
| 28 | #
|
| 29 | # THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
|
| 30 | # WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
|
| 31 | # LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
|
| 32 | # RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
|
| 33 | # THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
|
| 34 | #
|
| 35 | #*****************************************************************************
|
| 36 | #*
|
| 37 | #* Filename:
|
| 38 | #* ---------
|
| 39 | #* TCMQuery.pl
|
| 40 | #*
|
| 41 | #* Project:
|
| 42 | #* --------
|
| 43 | #*
|
| 44 | #*
|
| 45 | #* Description:
|
| 46 | #* ------------
|
| 47 | #* This script is used to get symbol, object, and section information from sym file
|
| 48 | #*
|
| 49 | #*
|
| 50 | #* Author:
|
| 51 | #* -------
|
| 52 | #* Carl Kao (mtk08237)
|
| 53 | #*
|
| 54 | #*------------------------------------------------------------------------------
|
| 55 | #* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!!
|
| 56 | #*============================================================================
|
| 57 | #****************************************************************************/
|
| 58 | #****************************************************************************
|
| 59 | # Included Modules
|
| 60 | #****************************************************************************
|
| 61 | use strict;
|
| 62 | BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' }
|
| 63 | use LinkerOutputParser;
|
| 64 | use File::Basename;
|
| 65 | use POSIX;
|
| 66 |
|
| 67 | my $TCMQuery_VERNO = " LR12_v0.03";
|
| 68 | # LR12_v0.03 , 2016/01/25, Memory Utility Refinement for LR12
|
| 69 | # LR12_v0.02 , 2016/12/15, fix memory utility .map file parsing feature for LR12 (64bit address)
|
| 70 | # LR12_v0.01 , 2016/10/26, add GrepSymbolByInputSection feature to memory utility
|
| 71 | # u0.01 , 2015/01/19, Initial revision for Memory Utility Refinement for LR11
|
| 72 |
|
| 73 | &Usage() if (($#ARGV != 2) && ($#ARGV != 3));
|
| 74 |
|
| 75 | my ($option, $region, $file1, $file2) = @ARGV;
|
| 76 |
|
| 77 | $file1 =~ s/\\/\\\\/;
|
| 78 | $file2 =~ s/\\/\\\\/;
|
| 79 |
|
| 80 | if(($option eq "-Q") || ($option eq "-q"))
|
| 81 | {
|
| 82 | &TCMQuery($region, $file1);
|
| 83 | }
|
| 84 | elsif(($option eq "-C") || ($option eq "-c"))
|
| 85 | {
|
| 86 | &TCMCompare($region, $file1, $file2);
|
| 87 | }
|
| 88 | elsif(($option eq "-S") || ($option eq "-s"))
|
| 89 | {
|
| 90 | my @SymbolInfo; #[[SymbolName, address, size], ...] sorted by address
|
| 91 | GetSymbolBySection($file1, $region, \@SymbolInfo);
|
| 92 | ListAllSymbolInfo(\@SymbolInfo);
|
| 93 | }
|
| 94 | elsif(($option eq "-IS") || ($option eq "-is"))
|
| 95 | {
|
| 96 | my @SymbolInfo; #[[SymbolName, Address, ObjectName, LibName, OutputSectionName, InputSectionName, InputSectionSize, SymbolSize], ...] sorted by address
|
| 97 | GetSymbolByOutputSection($file1, $file2, $region, \@SymbolInfo);
|
| 98 | ListAllSymbolAsMachineReadable(\@SymbolInfo, $region);
|
| 99 | }
|
| 100 | elsif(($option eq "-SC") || ($option eq "-sc"))
|
| 101 | {
|
| 102 | my @SymbolInfo1; #[[SymbolName, address, size], ...] sorted by address
|
| 103 | GetSymbolBySection($file1, $region, \@SymbolInfo1);
|
| 104 | my @SymbolInfo2; #[[SymbolName, address, size], ...] sorted by address
|
| 105 | GetSymbolBySection($file2, $region, \@SymbolInfo2);
|
| 106 | my $diff_href = DiffSymbolInfo(\@SymbolInfo1, \@SymbolInfo2);
|
| 107 | ListDiffSymbolInfo($diff_href, 0);
|
| 108 | }
|
| 109 | elsif(($option eq "-SCE") || ($option eq "-sce")) # section compare only in empty symbol
|
| 110 | {
|
| 111 | my @SymbolInfo1; #[[SymbolName, address, size], ...] sorted by address
|
| 112 | GetSymbolBySection($file1, $region, \@SymbolInfo1);
|
| 113 | my @SymbolInfo2; #[[SymbolName, address, size], ...] sorted by address
|
| 114 | GetSymbolBySection($file2, $region, \@SymbolInfo2);
|
| 115 | my $diff_href = DiffSymbolInfo(\@SymbolInfo1, \@SymbolInfo2);
|
| 116 | ListDiffSymbolInfo($diff_href, 1);
|
| 117 | }
|
| 118 | elsif(($option eq "-SO") || ($option eq "-so")) # parse symbols in specific lib
|
| 119 | {
|
| 120 | my @SymbolInfo;
|
| 121 | my $str_obj = $region;
|
| 122 | GetSymbolByObj($file1,$file2,$str_obj,\@SymbolInfo);
|
| 123 | ListAllSymbolAsMachineReadable(\@SymbolInfo,$str_obj);
|
| 124 | }
|
| 125 | elsif(($option eq "-SL") || ($option eq "-sl")) # parse symbols in specific obj
|
| 126 | {
|
| 127 | my @SymbolInfo;
|
| 128 | my $str_lib = $region;
|
| 129 | GetSymbolByLib($file1,$file2,$str_lib,\@SymbolInfo);
|
| 130 | ListAllSymbolAsMachineReadable(\@SymbolInfo,$str_lib);
|
| 131 | }
|
| 132 | elsif(($option eq "-ST") || ($option eq "-st")) # parse symbols whose size greater than specific size.
|
| 133 | {
|
| 134 | my @SymbolInfo;
|
| 135 | my $sym_size = $region;
|
| 136 | GetSymbolByThreshold($file1,$file2,$sym_size,\@SymbolInfo);
|
| 137 | ListAllSymbolAsMachineReadable(\@SymbolInfo,$sym_size);
|
| 138 | }
|
| 139 | elsif(($option eq "-SF") || ($option eq "-sf")) # parse fill info
|
| 140 | {
|
| 141 | my $FillInfo_href;
|
| 142 | &LinkerOutputParser::FileParse($region);
|
| 143 | $FillInfo_href = &LinkerOutputParser::GetFillInfo();
|
| 144 | ListFillInfo($FillInfo_href);
|
| 145 | }
|
| 146 | else
|
| 147 | {
|
| 148 | &Usage();
|
| 149 | }
|
| 150 |
|
| 151 | sub GetSymbolBySection
|
| 152 | {
|
| 153 | my ($symfile, $strSection, $SymbolInfo_aref) = @_;
|
| 154 | LinkerOutputParser::FileParse($symfile);
|
| 155 | my @regions = split(/\,/, $strSection);
|
| 156 | foreach my $section (@regions)
|
| 157 | {
|
| 158 | if($section =~ /SPRAM/i or $section eq "L2SRAM")
|
| 159 | {
|
| 160 | my $exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1);
|
| 161 | if (defined $exeregion_aref)
|
| 162 | {
|
| 163 | foreach my $temp(@$exeregion_aref)
|
| 164 | {
|
| 165 | if ($temp =~ /$section/i)
|
| 166 | {
|
| 167 | my $temp1_aref = LinkerOutputParser::GrepSymbolBySection($temp);
|
| 168 | push @$SymbolInfo_aref, @$temp1_aref;
|
| 169 | }
|
| 170 | }
|
| 171 | }
|
| 172 | }
|
| 173 | else
|
| 174 | {
|
| 175 | my $temp_aref = LinkerOutputParser::GrepSymbolBySection($section);
|
| 176 | push(@$SymbolInfo_aref , @$temp_aref);
|
| 177 | }
|
| 178 | }
|
| 179 | }
|
| 180 |
|
| 181 | sub GetSymbolByOutputSection
|
| 182 | {
|
| 183 | my ($mapfile, $symfile, $strSectionNameInRegularExp, $SymbolInfo_aref) = @_;
|
| 184 | my $temp_aref;
|
| 185 |
|
| 186 | LinkerOutputParser::FileParse($symfile);
|
| 187 |
|
| 188 | #list all symbol
|
| 189 | if($strSectionNameInRegularExp =~ /^all$/)
|
| 190 | {
|
| 191 | $temp_aref = GetAllSymbol($symfile);
|
| 192 | }
|
| 193 | else
|
| 194 | {
|
| 195 | $temp_aref = LinkerOutputParser::GrepSymbolByOutputSection($strSectionNameInRegularExp);
|
| 196 | }
|
| 197 |
|
| 198 | # remove inline functions
|
| 199 | my $idx=0;
|
| 200 | foreach (@{$temp_aref})
|
| 201 | {
|
| 202 | delete @{$temp_aref}[$idx] if(@$_[3] eq "00000000");
|
| 203 | $idx++;
|
| 204 | }
|
| 205 | @{$temp_aref} = grep { defined($_) } @{$temp_aref};
|
| 206 |
|
| 207 | # append symbol obj/lib name to array if symbol exist in map file
|
| 208 | AppendLibAttriToSymbol($mapfile,$temp_aref);
|
| 209 | push @$SymbolInfo_aref, @$temp_aref;
|
| 210 | }
|
| 211 |
|
| 212 | sub GetSymbolByObj{
|
| 213 | my ($mapfile, $symfile, $str_obj, $SymbolInfo_aref) = @_;
|
| 214 |
|
| 215 | my $symbol_aref = GetAllSymbol($symfile);
|
| 216 | AppendLibAttriToSymbol($mapfile, $symbol_aref);
|
| 217 |
|
| 218 | #list all symbol
|
| 219 | if($str_obj =~ /^all$/)
|
| 220 | {
|
| 221 | push(@$SymbolInfo_aref,@$symbol_aref);
|
| 222 | }
|
| 223 | else
|
| 224 | {
|
| 225 | my %obj = map{$_.".obj" => 1} split(/\,/, $str_obj);
|
| 226 | foreach(@{$symbol_aref})
|
| 227 | {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName]
|
| 228 | push(@$SymbolInfo_aref,$_) if($_->[5] && $obj{$_->[5]});
|
| 229 | }
|
| 230 | }
|
| 231 | }
|
| 232 |
|
| 233 | sub GetSymbolByLib{
|
| 234 | my ($mapfile, $symfile, $str_lib, $SymbolInfo_aref) = @_;
|
| 235 |
|
| 236 | my $symbol_aref = GetAllSymbol($symfile);
|
| 237 | AppendLibAttriToSymbol($mapfile, $symbol_aref);
|
| 238 |
|
| 239 | #list all symbol
|
| 240 | if($str_lib =~ /^all$/)
|
| 241 | {
|
| 242 | push(@$SymbolInfo_aref,@$symbol_aref);
|
| 243 | }
|
| 244 | else
|
| 245 | {
|
| 246 | my %lib = map{$_.".a" => 1} split(/\,/, $str_lib);
|
| 247 | foreach(@$symbol_aref)
|
| 248 | {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName]
|
| 249 | push(@$SymbolInfo_aref,$_) if($_->[6] && $lib{$_->[6]});
|
| 250 | }
|
| 251 | }
|
| 252 | }
|
| 253 |
|
| 254 | sub GetSymbolByThreshold{
|
| 255 | my ($mapfile, $symfile, $sym_size, $SymbolInfo_aref) = @_;
|
| 256 |
|
| 257 | my $symbol_aref = GetAllSymbol($symfile);
|
| 258 | AppendLibAttriToSymbol($mapfile, $symbol_aref);
|
| 259 |
|
| 260 | #list all symbol
|
| 261 | foreach(@$symbol_aref)
|
| 262 | {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName]
|
| 263 | push(@$SymbolInfo_aref,$_) if($_->[4] >= $sym_size);
|
| 264 | }
|
| 265 | }
|
| 266 |
|
| 267 | sub DiffSymbolInfo
|
| 268 | {
|
| 269 | my ($SymInfo1_aref, $SymInfo2_aref) = @_;
|
| 270 | my %diff;
|
| 271 | foreach my $item (@$SymInfo1_aref)
|
| 272 | {
|
| 273 | if(!exists $diff{$item->[SymTable::Name]})
|
| 274 | {
|
| 275 | $diff{$item->[SymTable::Name]} = [ $item->[SymTable::Size] , -1, $item->[SymTable::Region]];
|
| 276 | }
|
| 277 | else
|
| 278 | {
|
| 279 | $diff{$item->[SymTable::Name]."+"} = [ $item->[SymTable::Size] , -1, $item->[SymTable::Region]];
|
| 280 | }
|
| 281 | }
|
| 282 | foreach my $item (@$SymInfo2_aref)
|
| 283 | {
|
| 284 | if(exists $diff{$item->[SymTable::Name]})
|
| 285 | {
|
| 286 | $diff{$item->[SymTable::Name]}[1] = $item->[SymTable::Size];
|
| 287 | }
|
| 288 | else
|
| 289 | {
|
| 290 | $diff{$item->[SymTable::Name]} = [ -1, $item->[SymTable::Size], $item->[SymTable::Region]];
|
| 291 | }
|
| 292 | }
|
| 293 | return \%diff;
|
| 294 | }
|
| 295 |
|
| 296 | sub ListDiffSymbolInfo
|
| 297 | {
|
| 298 | my ($diff_href, $bListEmptyOnly) = @_;
|
| 299 | print " $file1 \nvs. $file2\n";
|
| 300 | print "SymbolName Size1 Size2\n";
|
| 301 | print "*********************************************************************************************************************\n";
|
| 302 | my $strRegion;
|
| 303 | my ($nTotalSize1, $nTotalSize2) = (0,0);
|
| 304 | foreach my $key (sort keys %$diff_href)
|
| 305 | {
|
| 306 | my $strSize1 = $diff_href->{$key}[0] eq "-1" ? "" : $diff_href->{$key}[0];
|
| 307 | my $strSize2 = $diff_href->{$key}[1] eq "-1" ? "" : $diff_href->{$key}[1];
|
| 308 | next if(($strSize1 eq $strSize2));
|
| 309 | if($bListEmptyOnly)
|
| 310 | {
|
| 311 | next if(!($diff_href->{$key}[0] eq "-1" or $diff_href->{$key}[1] eq "-1"));
|
| 312 | }
|
| 313 | $nTotalSize1 += $strSize1;
|
| 314 | $nTotalSize2 += $strSize2;
|
| 315 | $~ = "DIFF";
|
| 316 | format DIFF =
|
| 317 | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<<
|
| 318 | $key,$strSize1,$strSize2
|
| 319 | .
|
| 320 | write;
|
| 321 | }
|
| 322 | print "*********************************************************************************************************************\n";
|
| 323 | $~ = "TOTALDIFF";
|
| 324 | format TOTALDIFF =
|
| 325 | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<<
|
| 326 | 'Total',$nTotalSize1,$nTotalSize2
|
| 327 | .
|
| 328 | write;
|
| 329 | }
|
| 330 |
|
| 331 | sub ListAllSymbolInfo
|
| 332 | {
|
| 333 | my ($SymInfo_aref) = @_;
|
| 334 | print "[Section]\n";
|
| 335 | print "Address Size Group Symbol Name\n";
|
| 336 | print "*********************************************************************************************************************\n";
|
| 337 | my $strSection;
|
| 338 | my $nNextAddress = 0;
|
| 339 | my $nIndex = 0;
|
| 340 | foreach my $item (@$SymInfo_aref)
|
| 341 | {
|
| 342 | if($item->[SymTable::Region] ne $strSection)
|
| 343 | {
|
| 344 | $strSection = $item->[SymTable::Region];
|
| 345 | print "[$strSection]\n";
|
| 346 | }
|
| 347 |
|
| 348 | my $nSize = $item->[SymTable::Size];
|
| 349 | my $strSize = $nSize;
|
| 350 | if($nSize == 0)
|
| 351 | {
|
| 352 | if($nIndex+1 < scalar(@$SymInfo_aref) and $SymInfo_aref->[$nIndex+1][SymTable::Region] eq $strSection)
|
| 353 | {
|
| 354 | $nSize = hex($SymInfo_aref->[$nIndex+1][SymTable::Addr]) - hex($item->[SymTable::Addr]) ;
|
| 355 | }
|
| 356 | else
|
| 357 | {
|
| 358 | $nSize = "--";
|
| 359 | }
|
| 360 | $strSize = "0($nSize)";
|
| 361 | }
|
| 362 | $~ = "SYMBOLS";
|
| 363 | format SYMBOLS =
|
| 364 | @<<<<<<<<<<<<<@<<<<<<<<<@<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
| 365 | $item->[SymTable::Addr],$strSize,$item->[SymTable::Group],$item->[SymTable::Name],
|
| 366 | .
|
| 367 | write;
|
| 368 | $nIndex++;
|
| 369 | }
|
| 370 | }
|
| 371 |
|
| 372 | sub ListAllSymbolInfoBySpecify
|
| 373 | {
|
| 374 | my ($SymInfo_aref, $str_specify) = @_;
|
| 375 |
|
| 376 | #calculate each string elements' max length
|
| 377 | my @maxLengAry = ( length("SymbolName"), length("Address"), length("Attr"), length("OutputSectionName"), length("SymbolSize"), length("ObjectName"), length("LibName") );
|
| 378 | CalStringMaxLength($SymInfo_aref, \@maxLengAry);
|
| 379 | my $totalAryLength = 0;
|
| 380 | my $strFormatStr = "";
|
| 381 |
|
| 382 | for ( @maxLengAry )
|
| 383 | {
|
| 384 | $_ += 4;
|
| 385 | $totalAryLength += $_;
|
| 386 | }
|
| 387 |
|
| 388 | my $nTotalSize = 0;
|
| 389 |
|
| 390 | print "Specified parameter: $str_specify\n";
|
| 391 |
|
| 392 | print "LibName" . " " x ($maxLengAry[6]-length("LibName")) . # libc.a
|
| 393 | "ObjectName" . " " x ($maxLengAry[5]-length("ObjectName")) . # lib_a-memcpy.o
|
| 394 | "Address" . " " x ($maxLengAry[1]-length("Address")) . # 0x943a0000
|
| 395 | "Attr" . " " x ($maxLengAry[2]-length("Attr")) . # gF
|
| 396 | "OutputSectionName" . " " x ($maxLengAry[3]-length("OutputSectionName")) . # CACHED_EXTSRAM_L2CACHE_LOCK_DATA
|
| 397 | "SymbolSize" . " " x ($maxLengAry[4]-length("SymbolSize")) . # 924
|
| 398 | "SymbolName" . " " x ($maxLengAry[0]-length("SymbolName")) . "\n"; # memcpy
|
| 399 |
|
| 400 | print "*" x $totalAryLength . "\n";
|
| 401 |
|
| 402 | foreach (sort{ $a->[6] cmp $b->[6] #sort by lib
|
| 403 | or $a->[5] cmp $b->[5] #sort by obj
|
| 404 | or $a->[1] cmp $b->[1] #sort by address
|
| 405 | } @$SymInfo_aref)
|
| 406 | {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize, $strObjName, $strLibName];
|
| 407 | next if ($_->[4] == 0);#skip symbol whose size is 0.
|
| 408 | printf("%-${maxLengAry[6]}s", "@$_[6]"); #LibName
|
| 409 | printf("%-${maxLengAry[5]}s", "@$_[5]"); #ObjectName
|
| 410 | printf("%-${maxLengAry[1]}s", "@$_[1]"); #Address
|
| 411 | printf("%-${maxLengAry[2]}s", "@$_[2]"); #Attr
|
| 412 | printf("%-${maxLengAry[3]}s", "@$_[3]"); #OutputSectionName
|
| 413 | printf("%-${maxLengAry[4]}s", "@$_[4]"); #SymbolSize
|
| 414 | printf("%-${maxLengAry[0]}s", "@$_[0]"); #SymbolName
|
| 415 | print "\n";
|
| 416 | $nTotalSize += @$_[4];
|
| 417 | }
|
| 418 | print "*" x $totalAryLength . "\n";
|
| 419 | printf("Total size: %d bytes, %.3f KB\n\n\n", $nTotalSize, $nTotalSize/1024);
|
| 420 | }
|
| 421 |
|
| 422 |
|
| 423 | sub ListAllSymbolAsMachineReadable
|
| 424 | {
|
| 425 |
|
| 426 | my ($SymInfo_aref, $str_specify) = @_;
|
| 427 | #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
| 428 | #my $now = sprintf("%04d-%02d-%02d %02d:%02d:%06s", $year+1900, $mon+1, $mday, $hour, $min, $sec.".000");
|
| 429 |
|
| 430 | print "LibName,ObjectName,Address,Attr,OutputSectionName,SymbolSize,SymbolName\n";
|
| 431 |
|
| 432 | foreach (sort{ $a->[6] cmp $b->[6] #sort by lib
|
| 433 | or $a->[5] cmp $b->[5] #sort by obj
|
| 434 | or $a->[1] cmp $b->[1] #sort by address
|
| 435 | or $a->[0] cmp $b->[0] #sort by symbol name
|
| 436 | } @$SymInfo_aref)
|
| 437 | {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize, $strObjName, $strLibName];
|
| 438 | next if ($_->[4] == 0); #skip symbol whose size is 0.
|
| 439 | #printf("%s,",$now); #timestamp
|
| 440 | printf("%s,", "@$_[6]"); #LibName
|
| 441 | printf("%s,", "@$_[5]"); #ObjectName
|
| 442 | printf("%s,", "@$_[1]"); #Address
|
| 443 | printf("%s,", "@$_[2]"); #Attr
|
| 444 | printf("%s,", "@$_[3]"); #OutputSectionName
|
| 445 | printf("%s,", "@$_[4]"); #SymbolSize
|
| 446 | printf("%s", "@$_[0]"); #SymbolName
|
| 447 | print "\n";
|
| 448 | }
|
| 449 | }
|
| 450 |
|
| 451 | sub ListFillInfo
|
| 452 | {
|
| 453 | my ($FillInfo_href) = @_;
|
| 454 |
|
| 455 | print "Address,Fill_Size,Attr,Object_Info,Libinfo\n";
|
| 456 |
|
| 457 | foreach (sort{$$FillInfo_href{$a}->[0] cmp $$FillInfo_href{$b}->[0]} keys %{$FillInfo_href})
|
| 458 | {
|
| 459 | printf("%s,", $$FillInfo_href{$_}->[0]);
|
| 460 | printf("%s,", $$FillInfo_href{$_}->[1]);
|
| 461 | printf("%s,", $$FillInfo_href{$_}->[2]);
|
| 462 | printf("%s,", $$FillInfo_href{$_}->[3]);
|
| 463 | printf("%s", $$FillInfo_href{$_}->[4]) if $$FillInfo_href{$_}->[4];
|
| 464 | print "\n";
|
| 465 | }
|
| 466 | }
|
| 467 |
|
| 468 | sub TCMQuery
|
| 469 | {
|
| 470 | my ($ExeRegion, $file) = @_;
|
| 471 |
|
| 472 | my ($objs_aref, $RO_href, $RW_href, $ZI_href) = &GetAllOBJ($ExeRegion, $file);
|
| 473 | print "Object_Name RO_Size RW_Size ZI_Size\n";
|
| 474 | print "***********************************************************************************************\n";
|
| 475 |
|
| 476 | my $total_RO;
|
| 477 | my $total_RW;
|
| 478 | my $total_ZI;
|
| 479 |
|
| 480 | foreach my $temp(sort @$objs_aref)
|
| 481 | {
|
| 482 | $~ = "LIS_QUERY";
|
| 483 | format LIS_QUERY =
|
| 484 | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<
|
| 485 | $temp,$$RO_href{$temp},$$RW_href{$temp},$$ZI_href{$temp}
|
| 486 | .
|
| 487 |
|
| 488 | write;
|
| 489 | $total_RO += $$RO_href{$temp};
|
| 490 | $total_RW += $$RW_href{$temp};
|
| 491 | $total_ZI += $$ZI_href{$temp};
|
| 492 | }
|
| 493 | $~ = "LIS_QUERY_TOTAL";
|
| 494 | format LIS_QUERY_TOTAL =
|
| 495 | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<
|
| 496 | "Total",$total_RO,$total_RW,$total_ZI
|
| 497 | .
|
| 498 |
|
| 499 | write;
|
| 500 |
|
| 501 | print "***********************************************************************************************\n";
|
| 502 | }
|
| 503 |
|
| 504 | sub TCMCompare
|
| 505 | {
|
| 506 | my ($ExeRegion, $file1, $file2) = @_;
|
| 507 | my ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href, $objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href);
|
| 508 |
|
| 509 | ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href) = &GetAllOBJ($ExeRegion, $file1);
|
| 510 | ($objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href) = &GetAllOBJ($ExeRegion, $file2);
|
| 511 |
|
| 512 | my @objs1 = @$objs1_aref;
|
| 513 | my @objs2 = @$objs2_aref;
|
| 514 |
|
| 515 | my %objs1 = map{$_ => 1} @objs1;
|
| 516 | my %objs2 = map{$_ => 1} @objs2;
|
| 517 | my @arr = map{$_ => 1} @objs1;
|
| 518 |
|
| 519 | my @inter = grep {$objs1{$_}} @objs2;
|
| 520 |
|
| 521 | my %merge = map {$_ => 1} @objs1,@objs2;
|
| 522 | my @merge = sort keys (%merge);
|
| 523 |
|
| 524 | my @objs1_only = grep {!$objs2{$_}} @merge;
|
| 525 | my @objs2_only = grep {!$objs1{$_}} @merge;
|
| 526 |
|
| 527 | print "Compare result as below:\n";
|
| 528 |
|
| 529 |
|
| 530 | print "**************************************************************************************************************************************\n";
|
| 531 | print " Codebase1 Codebase2 Diff\n";
|
| 532 | print "ObjectName ROSize;RWSize;ZISize ROSize;RWSize;ZISize ROSize;RWSize;ZISize\n";
|
| 533 | print "**************************************************************************************************************************************\n";
|
| 534 |
|
| 535 | my $total_RO_1 = 0;
|
| 536 | my $total_RW_1 = 0;
|
| 537 | my $total_ZI_1 = 0;
|
| 538 | my $total_RO_2 = 0;
|
| 539 | my $total_RW_2 = 0;
|
| 540 | my $total_ZI_2 = 0;
|
| 541 | my $total_RO_diff = 0;
|
| 542 | my $total_RW_diff = 0;
|
| 543 | my $total_ZI_diff = 0;
|
| 544 | my $total_codebase1;
|
| 545 | my $total_codebase2;
|
| 546 | my $total_diff;
|
| 547 |
|
| 548 | foreach my $obj(@merge)
|
| 549 | {
|
| 550 | $$RO_2_href{$obj} = 0 if(!defined $$RO_2_href{$obj});
|
| 551 | $$RO_1_href{$obj} = 0 if(!defined $$RO_1_href{$obj});
|
| 552 | $$RW_2_href{$obj} = 0 if(!defined $$RW_2_href{$obj});
|
| 553 | $$RW_1_href{$obj} = 0 if(!defined $$RW_1_href{$obj});
|
| 554 | $$ZI_2_href{$obj} = 0 if(!defined $$ZI_2_href{$obj});
|
| 555 | $$ZI_1_href{$obj} = 0 if(!defined $$ZI_1_href{$obj});
|
| 556 |
|
| 557 | my $RO_diff = $$RO_2_href{$obj} - $$RO_1_href{$obj};
|
| 558 | my $RW_diff = $$RW_2_href{$obj} - $$RW_1_href{$obj};
|
| 559 | my $ZI_diff = $$ZI_2_href{$obj} - $$ZI_1_href{$obj};
|
| 560 |
|
| 561 | my $codebase1 = $$RO_1_href{$obj}.";".$$RW_1_href{$obj}.";".$$ZI_1_href{$obj};
|
| 562 | my $codebase2 = $$RO_2_href{$obj}.";".$$RW_2_href{$obj}.";".$$ZI_2_href{$obj};
|
| 563 | my $diff = $RO_diff.";".$RW_diff.";".$ZI_diff;
|
| 564 |
|
| 565 | $total_RO_1 += $$RO_1_href{$obj};
|
| 566 | $total_RW_1 += $$RW_1_href{$obj};
|
| 567 | $total_ZI_1 += $$ZI_1_href{$obj};
|
| 568 |
|
| 569 | $total_RO_2 += $$RO_2_href{$obj};
|
| 570 | $total_RW_2 += $$RW_2_href{$obj};
|
| 571 | $total_ZI_2 += $$ZI_2_href{$obj};
|
| 572 |
|
| 573 | $total_RO_diff += $RO_diff;
|
| 574 | $total_RW_diff += $RW_diff;
|
| 575 | $total_ZI_diff += $ZI_diff;
|
| 576 |
|
| 577 | $~ = "LIS_COMPARE";
|
| 578 | format LIS_COMPARE =
|
| 579 | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
| 580 | $obj,$codebase1,$codebase2,$diff
|
| 581 | .
|
| 582 |
|
| 583 | write;
|
| 584 | }
|
| 585 |
|
| 586 | $total_codebase1 = $total_RO_1.";".$total_RW_1.";".$total_ZI_1;
|
| 587 | $total_codebase2 = $total_RO_2.";".$total_RW_2.";".$total_ZI_2;
|
| 588 | $total_diff = $total_RO_diff.";".$total_RW_diff.";".$total_ZI_diff;
|
| 589 |
|
| 590 | $~ = "LIS_TOTAL";
|
| 591 | format LIS_TOTAL =
|
| 592 | @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
| 593 | "Total",$total_codebase1,$total_codebase2,$total_diff
|
| 594 | .
|
| 595 |
|
| 596 | write;
|
| 597 |
|
| 598 | print "**************************************************************************************************************************************\n";
|
| 599 | }
|
| 600 |
|
| 601 | sub GetAllOBJ
|
| 602 | {
|
| 603 | my ($ExeRegion, $file) = @_;
|
| 604 | my $symfile = $file;
|
| 605 | my $exeregion_aref;
|
| 606 |
|
| 607 | if($file =~ /\.map$/)
|
| 608 | {
|
| 609 | $symfile =~ s/map/sym/;
|
| 610 | if(!-f $symfile)
|
| 611 | {
|
| 612 | my $file = basename($symfile);
|
| 613 | my $dirname = dirname($symfile);
|
| 614 | $symfile = $dirname."\/dummy_$file";
|
| 615 | }
|
| 616 | &LinkerOutputParser::FileParse($symfile);
|
| 617 | }
|
| 618 | &LinkerOutputParser::FileParse($file);
|
| 619 | $exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1);
|
| 620 |
|
| 621 | my %objs;
|
| 622 | my @uni_objs;
|
| 623 | my %count;
|
| 624 | my %RO_Size;
|
| 625 | my %RW_Size;
|
| 626 | my %ZI_Size;
|
| 627 | my $nSectionCount=0;
|
| 628 | my $strListSections = "List of Sections:\n";
|
| 629 | my $strLast = "";
|
| 630 | if (defined $exeregion_aref)
|
| 631 | {
|
| 632 | foreach my $temp(@$exeregion_aref)
|
| 633 | {
|
| 634 | next if ($temp !~ /$ExeRegion/i);
|
| 635 | if (($ExeRegion =~ /[D|I].+\d$/i) && ($temp =~ /DYNAMIC_SECTION/i))
|
| 636 | { # add this confition for query DSPRAM0 + DSPRAM0_ZI. User treat them as single section
|
| 637 | $strLast .= "no overlap (dynamic loading) section: $temp\n";
|
| 638 | next;
|
| 639 | }
|
| 640 | my $obj_aref = &LinkerOutputParser::GetObjByExeRegion($temp);
|
| 641 | if (defined $obj_aref)
|
| 642 | {
|
| 643 | map { $objs{$_} = 1} @$obj_aref;
|
| 644 | }
|
| 645 | $strListSections .= sprintf("\tSection %3d: %s", $nSectionCount++, $temp);
|
| 646 | $strListSections .= (($temp =~ /DYNAMIC_SECTION/i) ? sprintf(" (overlap section)\n") : "\n");
|
| 647 | }
|
| 648 | }
|
| 649 | print $strListSections.$strLast."\n\n";
|
| 650 |
|
| 651 | foreach my $obj(keys %objs)
|
| 652 | {
|
| 653 | push (@uni_objs, $obj);
|
| 654 | my ($nRO_Size, $nRW_Size, $nZI_Size);
|
| 655 | if (defined $exeregion_aref)
|
| 656 | {
|
| 657 | foreach my $temp(@$exeregion_aref)
|
| 658 | {
|
| 659 | next if ($temp !~ /$ExeRegion/i);
|
| 660 |
|
| 661 | if($file =~ /\.map$/)
|
| 662 | {
|
| 663 | if ($obj =~ /\.o|\*\S*\*|stub/) #(/\*fill\*\s+(0x\w+)\s+(0x\w+)/)
|
| 664 | {
|
| 665 | $nRO_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "RO");
|
| 666 | $nRW_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "RW");
|
| 667 | $nZI_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "ZI");
|
| 668 | _UpdateSize(\%RO_Size, $obj, $nRO_Size);
|
| 669 | _UpdateSize(\%RW_Size, $obj, $nRW_Size);
|
| 670 | _UpdateSize(\%ZI_Size, $obj, $nZI_Size);
|
| 671 | }
|
| 672 | }
|
| 673 | }
|
| 674 | }
|
| 675 |
|
| 676 | }
|
| 677 |
|
| 678 | return (\@uni_objs, \%RO_Size, \%RW_Size, \%ZI_Size);
|
| 679 | }
|
| 680 |
|
| 681 | #calculate each element in the array's max length
|
| 682 | #input: [[str1_1, str2_1, str3_1, ...], [str1_2, str2_2, str3_2, ...], ...]
|
| 683 | #output: [max_length_str1, max_length_str2, max_length_str3, ...]
|
| 684 | sub CalStringMaxLength
|
| 685 | {
|
| 686 | my ($CaluAry_aref, $MaxLengthAry_aref) = @_;
|
| 687 |
|
| 688 | foreach my $curAry_aref (@{$CaluAry_aref})
|
| 689 | {
|
| 690 | for (my $i=0 ; $i <= $#$MaxLengthAry_aref ; $i++)
|
| 691 | {
|
| 692 | my $curStrLength = length(@$curAry_aref[$i]);
|
| 693 | $MaxLengthAry_aref->[$i] = $curStrLength if $curStrLength > $MaxLengthAry_aref->[$i];
|
| 694 | }
|
| 695 | }
|
| 696 | }
|
| 697 |
|
| 698 | sub _UpdateSize
|
| 699 | {
|
| 700 | my ($href, $strKey, $nSize) = @_;
|
| 701 | if(exists $href->{$strKey})
|
| 702 | {
|
| 703 | $href->{$strKey} += $nSize;
|
| 704 | }
|
| 705 | else
|
| 706 | {
|
| 707 | $href->{$strKey} = $nSize;
|
| 708 | }
|
| 709 | }
|
| 710 |
|
| 711 | sub GetAllSymbol{
|
| 712 |
|
| 713 | my ($symfile) = @_;
|
| 714 |
|
| 715 | LinkerOutputParser::FileParse($symfile);
|
| 716 | my $symbol_aref = &LinkerOutputParser::GetSymbolTable();
|
| 717 |
|
| 718 | return $symbol_aref;
|
| 719 | }
|
| 720 |
|
| 721 | sub AppendLibAttriToSymbol{
|
| 722 |
|
| 723 | my ($mapfile, $symbol_aref) = @_;
|
| 724 |
|
| 725 | # append symbol obj/lib name to array if symbol exist in map file
|
| 726 | LinkerOutputParser::FileParse($mapfile);
|
| 727 | my $region_attr = LinkerOutputParser::GetExeRegionAttr();
|
| 728 |
|
| 729 | foreach (@{$symbol_aref})
|
| 730 | { #[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName]
|
| 731 | my @symbol_info = LinkerOutputParser::GetSymbolInfo($_->[1].".".$_->[0]);
|
| 732 | my $strLibName = undef;
|
| 733 | my $obj_lib_by_addr = undef;
|
| 734 |
|
| 735 | $_->[2] = _updateAttr($_->[2], $region_attr->{$_->[3]});
|
| 736 |
|
| 737 | if (@symbol_info)
|
| 738 | {
|
| 739 | #get non-static symbol info
|
| 740 | #[$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize]
|
| 741 | $_->[4] = $symbol_info[6] > $_->[4] ? $symbol_info[6] : $_->[4];#update symbol size
|
| 742 | $_->[5] = $symbol_info[2];# obj name
|
| 743 | $_->[6] = $symbol_info[3];# lib name
|
| 744 | }
|
| 745 | elsif(@{$obj_lib_by_addr = LinkerOutputParser::ListObjLibByAddr($_->[1])})
|
| 746 | {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName];
|
| 747 | if($#$_ == 4 && $_->[0] !~ /^_ZN/)
|
| 748 | {
|
| 749 | $_->[4] = 0;
|
| 750 | }
|
| 751 | $_->[5] = $obj_lib_by_addr->[0];# obj name
|
| 752 | $_->[6] = $obj_lib_by_addr->[1];# lib name
|
| 753 | }
|
| 754 | elsif($#$_ == 5 && @{$strLibName = LinkerOutputParser::ListLibByObj($_->[-1])})
|
| 755 | {
|
| 756 | next if ($#$strLibName > 1);
|
| 757 | $_->[6] = $strLibName->[0];# lib name
|
| 758 | }
|
| 759 | }
|
| 760 | return $symbol_aref;
|
| 761 | }
|
| 762 |
|
| 763 | sub _updateAttr
|
| 764 | {
|
| 765 | my ($attr_group, $attr_sec) = @_;
|
| 766 |
|
| 767 | if($attr_sec =~ /RO/ && $attr_group =~ /F/)
|
| 768 | {
|
| 769 | return "RO_CODE";
|
| 770 | }
|
| 771 | elsif($attr_sec =~ /RO/ && $attr_group =~ /O/)
|
| 772 | {
|
| 773 | return "RO_DATA";
|
| 774 | }
|
| 775 | else
|
| 776 | {
|
| 777 | return $attr_sec;
|
| 778 | }
|
| 779 | }
|
| 780 |
|
| 781 | sub Usage
|
| 782 | {
|
| 783 | print <<"__EOFUSAGE";
|
| 784 |
|
| 785 | usage: perl TCMQuery.pl -Q INTSRAM map_file_path
|
| 786 | perl TCMQuery.pl -q INTSRAM map_file_path
|
| 787 | perl TCMQuery.pl -C INTSRAM map_file_path1 map_file_path2
|
| 788 | perl TCMQuery.pl -c INTSRAM map_file_path1 map_file_path2
|
| 789 | perl TCMQuery.pl -S INTSRAM sym_file_path
|
| 790 | perl TCMQuery.pl -s INTSRAM sym_file_path
|
| 791 |
|
| 792 | map_file_path1: map file path for codebase1 you want to compare
|
| 793 | map_file_path2: map file path for codebase2 you want to compare
|
| 794 |
|
| 795 | e.g.
|
| 796 | perl TCMQuery.pl -Q INTSRAM "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map"
|
| 797 | perl TCMQuery.pl -C INTSRAM "E:\\mtk80506\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map" "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map"
|
| 798 |
|
| 799 | __EOFUSAGE
|
| 800 | exit 1;
|
| 801 | }
|