| #!/usr/bin/perl | |
| # | |
| # Copyright Statement: | |
| # -------------------- | |
| # This software is protected by Copyright and the information contained | |
| # herein is confidential. The software may not be copied and the information | |
| # contained herein may not be used or disclosed except with the written | |
| # permission of MediaTek Inc. (C) 2006 | |
| # | |
| # BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES | |
| # THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") | |
| # RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON | |
| # AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, | |
| # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF | |
| # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. | |
| # NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE | |
| # SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR | |
| # SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH | |
| # THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO | |
| # NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S | |
| # SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. | |
| # | |
| # BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE | |
| # LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, | |
| # AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, | |
| # OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO | |
| # MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. | |
| # | |
| # THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE | |
| # WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF | |
| # LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND | |
| # RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER | |
| # THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). | |
| # | |
| #***************************************************************************** | |
| #* | |
| #* Filename: | |
| #* --------- | |
| #* TCMQuery.pl | |
| #* | |
| #* Project: | |
| #* -------- | |
| #* | |
| #* | |
| #* Description: | |
| #* ------------ | |
| #* This script is used to get symbol, object, and section information from sym file | |
| #* | |
| #* | |
| #* Author: | |
| #* ------- | |
| #* Carl Kao (mtk08237) | |
| #* | |
| #*------------------------------------------------------------------------------ | |
| #* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! | |
| #*============================================================================ | |
| #****************************************************************************/ | |
| #**************************************************************************** | |
| # Included Modules | |
| #**************************************************************************** | |
| use strict; | |
| BEGIN { push @INC, "./" , '../', './tools/', './tools/MemoryUtility/' } | |
| use LinkerOutputParser; | |
| use File::Basename; | |
| use POSIX; | |
| my $TCMQuery_VERNO = " LR12_v0.03"; | |
| # LR12_v0.03 , 2016/01/25, Memory Utility Refinement for LR12 | |
| # LR12_v0.02 , 2016/12/15, fix memory utility .map file parsing feature for LR12 (64bit address) | |
| # LR12_v0.01 , 2016/10/26, add GrepSymbolByInputSection feature to memory utility | |
| # u0.01 , 2015/01/19, Initial revision for Memory Utility Refinement for LR11 | |
| &Usage() if (($#ARGV != 2) && ($#ARGV != 3)); | |
| my ($option, $region, $file1, $file2) = @ARGV; | |
| $file1 =~ s/\\/\\\\/; | |
| $file2 =~ s/\\/\\\\/; | |
| if(($option eq "-Q") || ($option eq "-q")) | |
| { | |
| &TCMQuery($region, $file1); | |
| } | |
| elsif(($option eq "-C") || ($option eq "-c")) | |
| { | |
| &TCMCompare($region, $file1, $file2); | |
| } | |
| elsif(($option eq "-S") || ($option eq "-s")) | |
| { | |
| my @SymbolInfo; #[[SymbolName, address, size], ...] sorted by address | |
| GetSymbolBySection($file1, $region, \@SymbolInfo); | |
| ListAllSymbolInfo(\@SymbolInfo); | |
| } | |
| elsif(($option eq "-IS") || ($option eq "-is")) | |
| { | |
| my @SymbolInfo; #[[SymbolName, Address, ObjectName, LibName, OutputSectionName, InputSectionName, InputSectionSize, SymbolSize], ...] sorted by address | |
| GetSymbolByOutputSection($file1, $file2, $region, \@SymbolInfo); | |
| ListAllSymbolAsMachineReadable(\@SymbolInfo, $region); | |
| } | |
| elsif(($option eq "-SC") || ($option eq "-sc")) | |
| { | |
| my @SymbolInfo1; #[[SymbolName, address, size], ...] sorted by address | |
| GetSymbolBySection($file1, $region, \@SymbolInfo1); | |
| my @SymbolInfo2; #[[SymbolName, address, size], ...] sorted by address | |
| GetSymbolBySection($file2, $region, \@SymbolInfo2); | |
| my $diff_href = DiffSymbolInfo(\@SymbolInfo1, \@SymbolInfo2); | |
| ListDiffSymbolInfo($diff_href, 0); | |
| } | |
| elsif(($option eq "-SCE") || ($option eq "-sce")) # section compare only in empty symbol | |
| { | |
| my @SymbolInfo1; #[[SymbolName, address, size], ...] sorted by address | |
| GetSymbolBySection($file1, $region, \@SymbolInfo1); | |
| my @SymbolInfo2; #[[SymbolName, address, size], ...] sorted by address | |
| GetSymbolBySection($file2, $region, \@SymbolInfo2); | |
| my $diff_href = DiffSymbolInfo(\@SymbolInfo1, \@SymbolInfo2); | |
| ListDiffSymbolInfo($diff_href, 1); | |
| } | |
| elsif(($option eq "-SO") || ($option eq "-so")) # parse symbols in specific lib | |
| { | |
| my @SymbolInfo; | |
| my $str_obj = $region; | |
| GetSymbolByObj($file1,$file2,$str_obj,\@SymbolInfo); | |
| ListAllSymbolAsMachineReadable(\@SymbolInfo,$str_obj); | |
| } | |
| elsif(($option eq "-SL") || ($option eq "-sl")) # parse symbols in specific obj | |
| { | |
| my @SymbolInfo; | |
| my $str_lib = $region; | |
| GetSymbolByLib($file1,$file2,$str_lib,\@SymbolInfo); | |
| ListAllSymbolAsMachineReadable(\@SymbolInfo,$str_lib); | |
| } | |
| elsif(($option eq "-ST") || ($option eq "-st")) # parse symbols whose size greater than specific size. | |
| { | |
| my @SymbolInfo; | |
| my $sym_size = $region; | |
| GetSymbolByThreshold($file1,$file2,$sym_size,\@SymbolInfo); | |
| ListAllSymbolAsMachineReadable(\@SymbolInfo,$sym_size); | |
| } | |
| elsif(($option eq "-SF") || ($option eq "-sf")) # parse fill info | |
| { | |
| my $FillInfo_href; | |
| &LinkerOutputParser::FileParse($region); | |
| $FillInfo_href = &LinkerOutputParser::GetFillInfo(); | |
| ListFillInfo($FillInfo_href); | |
| } | |
| else | |
| { | |
| &Usage(); | |
| } | |
| sub GetSymbolBySection | |
| { | |
| my ($symfile, $strSection, $SymbolInfo_aref) = @_; | |
| LinkerOutputParser::FileParse($symfile); | |
| my @regions = split(/\,/, $strSection); | |
| foreach my $section (@regions) | |
| { | |
| if($section =~ /SPRAM/i or $section eq "L2SRAM") | |
| { | |
| my $exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1); | |
| if (defined $exeregion_aref) | |
| { | |
| foreach my $temp(@$exeregion_aref) | |
| { | |
| if ($temp =~ /$section/i) | |
| { | |
| my $temp1_aref = LinkerOutputParser::GrepSymbolBySection($temp); | |
| push @$SymbolInfo_aref, @$temp1_aref; | |
| } | |
| } | |
| } | |
| } | |
| else | |
| { | |
| my $temp_aref = LinkerOutputParser::GrepSymbolBySection($section); | |
| push(@$SymbolInfo_aref , @$temp_aref); | |
| } | |
| } | |
| } | |
| sub GetSymbolByOutputSection | |
| { | |
| my ($mapfile, $symfile, $strSectionNameInRegularExp, $SymbolInfo_aref) = @_; | |
| my $temp_aref; | |
| LinkerOutputParser::FileParse($symfile); | |
| #list all symbol | |
| if($strSectionNameInRegularExp =~ /^all$/) | |
| { | |
| $temp_aref = GetAllSymbol($symfile); | |
| } | |
| else | |
| { | |
| $temp_aref = LinkerOutputParser::GrepSymbolByOutputSection($strSectionNameInRegularExp); | |
| } | |
| # remove inline functions | |
| my $idx=0; | |
| foreach (@{$temp_aref}) | |
| { | |
| delete @{$temp_aref}[$idx] if(@$_[3] eq "00000000"); | |
| $idx++; | |
| } | |
| @{$temp_aref} = grep { defined($_) } @{$temp_aref}; | |
| # append symbol obj/lib name to array if symbol exist in map file | |
| AppendLibAttriToSymbol($mapfile,$temp_aref); | |
| push @$SymbolInfo_aref, @$temp_aref; | |
| } | |
| sub GetSymbolByObj{ | |
| my ($mapfile, $symfile, $str_obj, $SymbolInfo_aref) = @_; | |
| my $symbol_aref = GetAllSymbol($symfile); | |
| AppendLibAttriToSymbol($mapfile, $symbol_aref); | |
| #list all symbol | |
| if($str_obj =~ /^all$/) | |
| { | |
| push(@$SymbolInfo_aref,@$symbol_aref); | |
| } | |
| else | |
| { | |
| my %obj = map{$_.".obj" => 1} split(/\,/, $str_obj); | |
| foreach(@{$symbol_aref}) | |
| {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName] | |
| push(@$SymbolInfo_aref,$_) if($_->[5] && $obj{$_->[5]}); | |
| } | |
| } | |
| } | |
| sub GetSymbolByLib{ | |
| my ($mapfile, $symfile, $str_lib, $SymbolInfo_aref) = @_; | |
| my $symbol_aref = GetAllSymbol($symfile); | |
| AppendLibAttriToSymbol($mapfile, $symbol_aref); | |
| #list all symbol | |
| if($str_lib =~ /^all$/) | |
| { | |
| push(@$SymbolInfo_aref,@$symbol_aref); | |
| } | |
| else | |
| { | |
| my %lib = map{$_.".a" => 1} split(/\,/, $str_lib); | |
| foreach(@$symbol_aref) | |
| {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName] | |
| push(@$SymbolInfo_aref,$_) if($_->[6] && $lib{$_->[6]}); | |
| } | |
| } | |
| } | |
| sub GetSymbolByThreshold{ | |
| my ($mapfile, $symfile, $sym_size, $SymbolInfo_aref) = @_; | |
| my $symbol_aref = GetAllSymbol($symfile); | |
| AppendLibAttriToSymbol($mapfile, $symbol_aref); | |
| #list all symbol | |
| foreach(@$symbol_aref) | |
| {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName,$strLibName] | |
| push(@$SymbolInfo_aref,$_) if($_->[4] >= $sym_size); | |
| } | |
| } | |
| sub DiffSymbolInfo | |
| { | |
| my ($SymInfo1_aref, $SymInfo2_aref) = @_; | |
| my %diff; | |
| foreach my $item (@$SymInfo1_aref) | |
| { | |
| if(!exists $diff{$item->[SymTable::Name]}) | |
| { | |
| $diff{$item->[SymTable::Name]} = [ $item->[SymTable::Size] , -1, $item->[SymTable::Region]]; | |
| } | |
| else | |
| { | |
| $diff{$item->[SymTable::Name]."+"} = [ $item->[SymTable::Size] , -1, $item->[SymTable::Region]]; | |
| } | |
| } | |
| foreach my $item (@$SymInfo2_aref) | |
| { | |
| if(exists $diff{$item->[SymTable::Name]}) | |
| { | |
| $diff{$item->[SymTable::Name]}[1] = $item->[SymTable::Size]; | |
| } | |
| else | |
| { | |
| $diff{$item->[SymTable::Name]} = [ -1, $item->[SymTable::Size], $item->[SymTable::Region]]; | |
| } | |
| } | |
| return \%diff; | |
| } | |
| sub ListDiffSymbolInfo | |
| { | |
| my ($diff_href, $bListEmptyOnly) = @_; | |
| print " $file1 \nvs. $file2\n"; | |
| print "SymbolName Size1 Size2\n"; | |
| print "*********************************************************************************************************************\n"; | |
| my $strRegion; | |
| my ($nTotalSize1, $nTotalSize2) = (0,0); | |
| foreach my $key (sort keys %$diff_href) | |
| { | |
| my $strSize1 = $diff_href->{$key}[0] eq "-1" ? "" : $diff_href->{$key}[0]; | |
| my $strSize2 = $diff_href->{$key}[1] eq "-1" ? "" : $diff_href->{$key}[1]; | |
| next if(($strSize1 eq $strSize2)); | |
| if($bListEmptyOnly) | |
| { | |
| next if(!($diff_href->{$key}[0] eq "-1" or $diff_href->{$key}[1] eq "-1")); | |
| } | |
| $nTotalSize1 += $strSize1; | |
| $nTotalSize2 += $strSize2; | |
| $~ = "DIFF"; | |
| format DIFF = | |
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<< | |
| $key,$strSize1,$strSize2 | |
| . | |
| write; | |
| } | |
| print "*********************************************************************************************************************\n"; | |
| $~ = "TOTALDIFF"; | |
| format TOTALDIFF = | |
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<@<<<<<<<<< | |
| 'Total',$nTotalSize1,$nTotalSize2 | |
| . | |
| write; | |
| } | |
| sub ListAllSymbolInfo | |
| { | |
| my ($SymInfo_aref) = @_; | |
| print "[Section]\n"; | |
| print "Address Size Group Symbol Name\n"; | |
| print "*********************************************************************************************************************\n"; | |
| my $strSection; | |
| my $nNextAddress = 0; | |
| my $nIndex = 0; | |
| foreach my $item (@$SymInfo_aref) | |
| { | |
| if($item->[SymTable::Region] ne $strSection) | |
| { | |
| $strSection = $item->[SymTable::Region]; | |
| print "[$strSection]\n"; | |
| } | |
| my $nSize = $item->[SymTable::Size]; | |
| my $strSize = $nSize; | |
| if($nSize == 0) | |
| { | |
| if($nIndex+1 < scalar(@$SymInfo_aref) and $SymInfo_aref->[$nIndex+1][SymTable::Region] eq $strSection) | |
| { | |
| $nSize = hex($SymInfo_aref->[$nIndex+1][SymTable::Addr]) - hex($item->[SymTable::Addr]) ; | |
| } | |
| else | |
| { | |
| $nSize = "--"; | |
| } | |
| $strSize = "0($nSize)"; | |
| } | |
| $~ = "SYMBOLS"; | |
| format SYMBOLS = | |
| @<<<<<<<<<<<<<@<<<<<<<<<@<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
| $item->[SymTable::Addr],$strSize,$item->[SymTable::Group],$item->[SymTable::Name], | |
| . | |
| write; | |
| $nIndex++; | |
| } | |
| } | |
| sub ListAllSymbolInfoBySpecify | |
| { | |
| my ($SymInfo_aref, $str_specify) = @_; | |
| #calculate each string elements' max length | |
| my @maxLengAry = ( length("SymbolName"), length("Address"), length("Attr"), length("OutputSectionName"), length("SymbolSize"), length("ObjectName"), length("LibName") ); | |
| CalStringMaxLength($SymInfo_aref, \@maxLengAry); | |
| my $totalAryLength = 0; | |
| my $strFormatStr = ""; | |
| for ( @maxLengAry ) | |
| { | |
| $_ += 4; | |
| $totalAryLength += $_; | |
| } | |
| my $nTotalSize = 0; | |
| print "Specified parameter: $str_specify\n"; | |
| print "LibName" . " " x ($maxLengAry[6]-length("LibName")) . # libc.a | |
| "ObjectName" . " " x ($maxLengAry[5]-length("ObjectName")) . # lib_a-memcpy.o | |
| "Address" . " " x ($maxLengAry[1]-length("Address")) . # 0x943a0000 | |
| "Attr" . " " x ($maxLengAry[2]-length("Attr")) . # gF | |
| "OutputSectionName" . " " x ($maxLengAry[3]-length("OutputSectionName")) . # CACHED_EXTSRAM_L2CACHE_LOCK_DATA | |
| "SymbolSize" . " " x ($maxLengAry[4]-length("SymbolSize")) . # 924 | |
| "SymbolName" . " " x ($maxLengAry[0]-length("SymbolName")) . "\n"; # memcpy | |
| print "*" x $totalAryLength . "\n"; | |
| foreach (sort{ $a->[6] cmp $b->[6] #sort by lib | |
| or $a->[5] cmp $b->[5] #sort by obj | |
| or $a->[1] cmp $b->[1] #sort by address | |
| } @$SymInfo_aref) | |
| {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize, $strObjName, $strLibName]; | |
| next if ($_->[4] == 0);#skip symbol whose size is 0. | |
| printf("%-${maxLengAry[6]}s", "@$_[6]"); #LibName | |
| printf("%-${maxLengAry[5]}s", "@$_[5]"); #ObjectName | |
| printf("%-${maxLengAry[1]}s", "@$_[1]"); #Address | |
| printf("%-${maxLengAry[2]}s", "@$_[2]"); #Attr | |
| printf("%-${maxLengAry[3]}s", "@$_[3]"); #OutputSectionName | |
| printf("%-${maxLengAry[4]}s", "@$_[4]"); #SymbolSize | |
| printf("%-${maxLengAry[0]}s", "@$_[0]"); #SymbolName | |
| print "\n"; | |
| $nTotalSize += @$_[4]; | |
| } | |
| print "*" x $totalAryLength . "\n"; | |
| printf("Total size: %d bytes, %.3f KB\n\n\n", $nTotalSize, $nTotalSize/1024); | |
| } | |
| sub ListAllSymbolAsMachineReadable | |
| { | |
| my ($SymInfo_aref, $str_specify) = @_; | |
| #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); | |
| #my $now = sprintf("%04d-%02d-%02d %02d:%02d:%06s", $year+1900, $mon+1, $mday, $hour, $min, $sec.".000"); | |
| print "LibName,ObjectName,Address,Attr,OutputSectionName,SymbolSize,SymbolName\n"; | |
| foreach (sort{ $a->[6] cmp $b->[6] #sort by lib | |
| or $a->[5] cmp $b->[5] #sort by obj | |
| or $a->[1] cmp $b->[1] #sort by address | |
| or $a->[0] cmp $b->[0] #sort by symbol name | |
| } @$SymInfo_aref) | |
| {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize, $strObjName, $strLibName]; | |
| next if ($_->[4] == 0); #skip symbol whose size is 0. | |
| #printf("%s,",$now); #timestamp | |
| printf("%s,", "@$_[6]"); #LibName | |
| printf("%s,", "@$_[5]"); #ObjectName | |
| printf("%s,", "@$_[1]"); #Address | |
| printf("%s,", "@$_[2]"); #Attr | |
| printf("%s,", "@$_[3]"); #OutputSectionName | |
| printf("%s,", "@$_[4]"); #SymbolSize | |
| printf("%s", "@$_[0]"); #SymbolName | |
| print "\n"; | |
| } | |
| } | |
| sub ListFillInfo | |
| { | |
| my ($FillInfo_href) = @_; | |
| print "Address,Fill_Size,Attr,Object_Info,Libinfo\n"; | |
| foreach (sort{$$FillInfo_href{$a}->[0] cmp $$FillInfo_href{$b}->[0]} keys %{$FillInfo_href}) | |
| { | |
| printf("%s,", $$FillInfo_href{$_}->[0]); | |
| printf("%s,", $$FillInfo_href{$_}->[1]); | |
| printf("%s,", $$FillInfo_href{$_}->[2]); | |
| printf("%s,", $$FillInfo_href{$_}->[3]); | |
| printf("%s", $$FillInfo_href{$_}->[4]) if $$FillInfo_href{$_}->[4]; | |
| print "\n"; | |
| } | |
| } | |
| sub TCMQuery | |
| { | |
| my ($ExeRegion, $file) = @_; | |
| my ($objs_aref, $RO_href, $RW_href, $ZI_href) = &GetAllOBJ($ExeRegion, $file); | |
| print "Object_Name RO_Size RW_Size ZI_Size\n"; | |
| print "***********************************************************************************************\n"; | |
| my $total_RO; | |
| my $total_RW; | |
| my $total_ZI; | |
| foreach my $temp(sort @$objs_aref) | |
| { | |
| $~ = "LIS_QUERY"; | |
| format LIS_QUERY = | |
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<< | |
| $temp,$$RO_href{$temp},$$RW_href{$temp},$$ZI_href{$temp} | |
| . | |
| write; | |
| $total_RO += $$RO_href{$temp}; | |
| $total_RW += $$RW_href{$temp}; | |
| $total_ZI += $$ZI_href{$temp}; | |
| } | |
| $~ = "LIS_QUERY_TOTAL"; | |
| format LIS_QUERY_TOTAL = | |
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<< | |
| "Total",$total_RO,$total_RW,$total_ZI | |
| . | |
| write; | |
| print "***********************************************************************************************\n"; | |
| } | |
| sub TCMCompare | |
| { | |
| my ($ExeRegion, $file1, $file2) = @_; | |
| my ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href, $objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href); | |
| ($objs1_aref, $RO_1_href, $RW_1_href, $ZI_1_href) = &GetAllOBJ($ExeRegion, $file1); | |
| ($objs2_aref, $RO_2_href, $RW_2_href, $ZI_2_href) = &GetAllOBJ($ExeRegion, $file2); | |
| my @objs1 = @$objs1_aref; | |
| my @objs2 = @$objs2_aref; | |
| my %objs1 = map{$_ => 1} @objs1; | |
| my %objs2 = map{$_ => 1} @objs2; | |
| my @arr = map{$_ => 1} @objs1; | |
| my @inter = grep {$objs1{$_}} @objs2; | |
| my %merge = map {$_ => 1} @objs1,@objs2; | |
| my @merge = sort keys (%merge); | |
| my @objs1_only = grep {!$objs2{$_}} @merge; | |
| my @objs2_only = grep {!$objs1{$_}} @merge; | |
| print "Compare result as below:\n"; | |
| print "**************************************************************************************************************************************\n"; | |
| print " Codebase1 Codebase2 Diff\n"; | |
| print "ObjectName ROSize;RWSize;ZISize ROSize;RWSize;ZISize ROSize;RWSize;ZISize\n"; | |
| print "**************************************************************************************************************************************\n"; | |
| my $total_RO_1 = 0; | |
| my $total_RW_1 = 0; | |
| my $total_ZI_1 = 0; | |
| my $total_RO_2 = 0; | |
| my $total_RW_2 = 0; | |
| my $total_ZI_2 = 0; | |
| my $total_RO_diff = 0; | |
| my $total_RW_diff = 0; | |
| my $total_ZI_diff = 0; | |
| my $total_codebase1; | |
| my $total_codebase2; | |
| my $total_diff; | |
| foreach my $obj(@merge) | |
| { | |
| $$RO_2_href{$obj} = 0 if(!defined $$RO_2_href{$obj}); | |
| $$RO_1_href{$obj} = 0 if(!defined $$RO_1_href{$obj}); | |
| $$RW_2_href{$obj} = 0 if(!defined $$RW_2_href{$obj}); | |
| $$RW_1_href{$obj} = 0 if(!defined $$RW_1_href{$obj}); | |
| $$ZI_2_href{$obj} = 0 if(!defined $$ZI_2_href{$obj}); | |
| $$ZI_1_href{$obj} = 0 if(!defined $$ZI_1_href{$obj}); | |
| my $RO_diff = $$RO_2_href{$obj} - $$RO_1_href{$obj}; | |
| my $RW_diff = $$RW_2_href{$obj} - $$RW_1_href{$obj}; | |
| my $ZI_diff = $$ZI_2_href{$obj} - $$ZI_1_href{$obj}; | |
| my $codebase1 = $$RO_1_href{$obj}.";".$$RW_1_href{$obj}.";".$$ZI_1_href{$obj}; | |
| my $codebase2 = $$RO_2_href{$obj}.";".$$RW_2_href{$obj}.";".$$ZI_2_href{$obj}; | |
| my $diff = $RO_diff.";".$RW_diff.";".$ZI_diff; | |
| $total_RO_1 += $$RO_1_href{$obj}; | |
| $total_RW_1 += $$RW_1_href{$obj}; | |
| $total_ZI_1 += $$ZI_1_href{$obj}; | |
| $total_RO_2 += $$RO_2_href{$obj}; | |
| $total_RW_2 += $$RW_2_href{$obj}; | |
| $total_ZI_2 += $$ZI_2_href{$obj}; | |
| $total_RO_diff += $RO_diff; | |
| $total_RW_diff += $RW_diff; | |
| $total_ZI_diff += $ZI_diff; | |
| $~ = "LIS_COMPARE"; | |
| format LIS_COMPARE = | |
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
| $obj,$codebase1,$codebase2,$diff | |
| . | |
| write; | |
| } | |
| $total_codebase1 = $total_RO_1.";".$total_RW_1.";".$total_ZI_1; | |
| $total_codebase2 = $total_RO_2.";".$total_RW_2.";".$total_ZI_2; | |
| $total_diff = $total_RO_diff.";".$total_RW_diff.";".$total_ZI_diff; | |
| $~ = "LIS_TOTAL"; | |
| format LIS_TOTAL = | |
| @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | |
| "Total",$total_codebase1,$total_codebase2,$total_diff | |
| . | |
| write; | |
| print "**************************************************************************************************************************************\n"; | |
| } | |
| sub GetAllOBJ | |
| { | |
| my ($ExeRegion, $file) = @_; | |
| my $symfile = $file; | |
| my $exeregion_aref; | |
| if($file =~ /\.map$/) | |
| { | |
| $symfile =~ s/map/sym/; | |
| if(!-f $symfile) | |
| { | |
| my $file = basename($symfile); | |
| my $dirname = dirname($symfile); | |
| $symfile = $dirname."\/dummy_$file"; | |
| } | |
| &LinkerOutputParser::FileParse($symfile); | |
| } | |
| &LinkerOutputParser::FileParse($file); | |
| $exeregion_aref = &LinkerOutputParser::ListAllExeRegion(1); | |
| my %objs; | |
| my @uni_objs; | |
| my %count; | |
| my %RO_Size; | |
| my %RW_Size; | |
| my %ZI_Size; | |
| my $nSectionCount=0; | |
| my $strListSections = "List of Sections:\n"; | |
| my $strLast = ""; | |
| if (defined $exeregion_aref) | |
| { | |
| foreach my $temp(@$exeregion_aref) | |
| { | |
| next if ($temp !~ /$ExeRegion/i); | |
| if (($ExeRegion =~ /[D|I].+\d$/i) && ($temp =~ /DYNAMIC_SECTION/i)) | |
| { # add this confition for query DSPRAM0 + DSPRAM0_ZI. User treat them as single section | |
| $strLast .= "no overlap (dynamic loading) section: $temp\n"; | |
| next; | |
| } | |
| my $obj_aref = &LinkerOutputParser::GetObjByExeRegion($temp); | |
| if (defined $obj_aref) | |
| { | |
| map { $objs{$_} = 1} @$obj_aref; | |
| } | |
| $strListSections .= sprintf("\tSection %3d: %s", $nSectionCount++, $temp); | |
| $strListSections .= (($temp =~ /DYNAMIC_SECTION/i) ? sprintf(" (overlap section)\n") : "\n"); | |
| } | |
| } | |
| print $strListSections.$strLast."\n\n"; | |
| foreach my $obj(keys %objs) | |
| { | |
| push (@uni_objs, $obj); | |
| my ($nRO_Size, $nRW_Size, $nZI_Size); | |
| if (defined $exeregion_aref) | |
| { | |
| foreach my $temp(@$exeregion_aref) | |
| { | |
| next if ($temp !~ /$ExeRegion/i); | |
| if($file =~ /\.map$/) | |
| { | |
| if ($obj =~ /\.o|\*\S*\*|stub/) #(/\*fill\*\s+(0x\w+)\s+(0x\w+)/) | |
| { | |
| $nRO_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "RO"); | |
| $nRW_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "RW"); | |
| $nZI_Size = &LinkerOutputParser::GetObjSizeByCatExeRegion($temp, $obj, "ZI"); | |
| _UpdateSize(\%RO_Size, $obj, $nRO_Size); | |
| _UpdateSize(\%RW_Size, $obj, $nRW_Size); | |
| _UpdateSize(\%ZI_Size, $obj, $nZI_Size); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return (\@uni_objs, \%RO_Size, \%RW_Size, \%ZI_Size); | |
| } | |
| #calculate each element in the array's max length | |
| #input: [[str1_1, str2_1, str3_1, ...], [str1_2, str2_2, str3_2, ...], ...] | |
| #output: [max_length_str1, max_length_str2, max_length_str3, ...] | |
| sub CalStringMaxLength | |
| { | |
| my ($CaluAry_aref, $MaxLengthAry_aref) = @_; | |
| foreach my $curAry_aref (@{$CaluAry_aref}) | |
| { | |
| for (my $i=0 ; $i <= $#$MaxLengthAry_aref ; $i++) | |
| { | |
| my $curStrLength = length(@$curAry_aref[$i]); | |
| $MaxLengthAry_aref->[$i] = $curStrLength if $curStrLength > $MaxLengthAry_aref->[$i]; | |
| } | |
| } | |
| } | |
| sub _UpdateSize | |
| { | |
| my ($href, $strKey, $nSize) = @_; | |
| if(exists $href->{$strKey}) | |
| { | |
| $href->{$strKey} += $nSize; | |
| } | |
| else | |
| { | |
| $href->{$strKey} = $nSize; | |
| } | |
| } | |
| sub GetAllSymbol{ | |
| my ($symfile) = @_; | |
| LinkerOutputParser::FileParse($symfile); | |
| my $symbol_aref = &LinkerOutputParser::GetSymbolTable(); | |
| return $symbol_aref; | |
| } | |
| sub AppendLibAttriToSymbol{ | |
| my ($mapfile, $symbol_aref) = @_; | |
| # append symbol obj/lib name to array if symbol exist in map file | |
| LinkerOutputParser::FileParse($mapfile); | |
| my $region_attr = LinkerOutputParser::GetExeRegionAttr(); | |
| foreach (@{$symbol_aref}) | |
| { #[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName] | |
| my @symbol_info = LinkerOutputParser::GetSymbolInfo($_->[1].".".$_->[0]); | |
| my $strLibName = undef; | |
| my $obj_lib_by_addr = undef; | |
| $_->[2] = _updateAttr($_->[2], $region_attr->{$_->[3]}); | |
| if (@symbol_info) | |
| { | |
| #get non-static symbol info | |
| #[$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize] | |
| $_->[4] = $symbol_info[6] > $_->[4] ? $symbol_info[6] : $_->[4];#update symbol size | |
| $_->[5] = $symbol_info[2];# obj name | |
| $_->[6] = $symbol_info[3];# lib name | |
| } | |
| elsif(@{$obj_lib_by_addr = LinkerOutputParser::ListObjLibByAddr($_->[1])}) | |
| {#[$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName]; | |
| if($#$_ == 4 && $_->[0] !~ /^_ZN/) | |
| { | |
| $_->[4] = 0; | |
| } | |
| $_->[5] = $obj_lib_by_addr->[0];# obj name | |
| $_->[6] = $obj_lib_by_addr->[1];# lib name | |
| } | |
| elsif($#$_ == 5 && @{$strLibName = LinkerOutputParser::ListLibByObj($_->[-1])}) | |
| { | |
| next if ($#$strLibName > 1); | |
| $_->[6] = $strLibName->[0];# lib name | |
| } | |
| } | |
| return $symbol_aref; | |
| } | |
| sub _updateAttr | |
| { | |
| my ($attr_group, $attr_sec) = @_; | |
| if($attr_sec =~ /RO/ && $attr_group =~ /F/) | |
| { | |
| return "RO_CODE"; | |
| } | |
| elsif($attr_sec =~ /RO/ && $attr_group =~ /O/) | |
| { | |
| return "RO_DATA"; | |
| } | |
| else | |
| { | |
| return $attr_sec; | |
| } | |
| } | |
| sub Usage | |
| { | |
| print <<"__EOFUSAGE"; | |
| usage: perl TCMQuery.pl -Q INTSRAM map_file_path | |
| perl TCMQuery.pl -q INTSRAM map_file_path | |
| perl TCMQuery.pl -C INTSRAM map_file_path1 map_file_path2 | |
| perl TCMQuery.pl -c INTSRAM map_file_path1 map_file_path2 | |
| perl TCMQuery.pl -S INTSRAM sym_file_path | |
| perl TCMQuery.pl -s INTSRAM sym_file_path | |
| map_file_path1: map file path for codebase1 you want to compare | |
| map_file_path2: map file path for codebase2 you want to compare | |
| e.g. | |
| perl TCMQuery.pl -Q INTSRAM "E:\\mtk80506\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00\\MT6280_EVB_R7R8_PCB01_hspa_MT6280_S00.map" | |
| 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" | |
| __EOFUSAGE | |
| exit 1; | |
| } |