blob: 80fd6956f7dfec11b84d6de32374e631d43b08f7 [file] [log] [blame]
#!/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:
#* ---------
#* MapFileParser.pm
#*
#* Project:
#* --------
#*
#*
#* Description:
#* ------------
#* This perl module is used to collect information from map file
#*
#*
#* Author:
#* -------
#* Carl Kao (mtk08237)
#*
#****************************************************************************/
use strict;
BEGIN{push(@INC,'../../tools/', './tools/', './tools/MemoryUtility/')};
use CommonUtility;
package SymbolInfoTable;
use constant SymbolName => 0;
use constant Addr => 1;
use constant ObjName => 2;
use constant LibName => 3;
use constant OutputSectionName => 4;
use constant InputSectionName => 5;
use constant Size => 6;
package MapFileParser;
my $VERNO = " u0.01";
# u0.01 , 2015/01/19, Initial revision for Memory Utility Refinement
my $g_MAPPath;
my %parent_of_symbol; #symbol info in "symbol table"
my %parent_obj_of_symbol; #symbol info in "symbol table"
my %parent_lib_of_symbol; #symbol info in "symbol table"
my %contained_obj; # obj contained in lib
my %related_lib; # lib related a obj
my %obj_size; # obj total size
my %lib_size; # lib total size
my %region_obj_size;
my %region_lib_size;
my %region_contained_obj;
my %region_obj;
my %region_contained_lib;
my @veneers;
my %obj_pad;
my %obj_lib_lookup;
my $obj_pad_count = 0;
my @pad;
my %g_discard_symbols; #$inputsection.".".$obj => $nSize;
my %obj_debuginfo;
my %lib_debuginfo;
my %OBJ_RO_Size; #{objname} => nSize
my %LIB_RO_Size; #{libname} => nSize
my %OBJ_RW_Size;
my %LIB_RW_Size;
my %OBJ_ZI_Size;
my %LIB_ZI_Size;
my %region_OBJ_RO_Size; #{regionname-objname} => nSize
my %region_OBJ_RW_Size;
my %region_OBJ_ZI_Size;
my @sections; # input section
my %symbol_info; #{$strSymbolName} => [strSymbolName, strAddress, strObjName, strLibName, strOutputSectionName, strInputSectionName, nInputSectionSize]
my %symbol_lookup_table; #{$SymbolName.".".$strObjName.".".$strLibName} => [strSymbolName, strAddress, strObjName, strLibName, strOutputSectionName, strInputSectionName, nInputSectionSize]
my %region_arribution;
my $g_fill; #record ** zero fill ** part
my %g_fill_info; #record all fill info.
#****************************************************************************
# oo >>> Finished
#****************************************************************************
return 1;
#****************************************************************************
# subroutine: MAP_die
# sample code: (message, __FILE__, __LINE__)
# input: $error_msg, $file, $line_no
#****************************************************************************
sub MAP_die
{
my ($error_msg, $file, $line_no) = (@_);
&CommonUtil::error_handler($error_msg, $file, $line_no, 'MAP');
}
#****************************************************************************
# subroutine: ParseMAP
# input: MAP Path string
# output: x
#****************************************************************************
sub initGlobalVariable
{
%parent_of_symbol = ();
%parent_obj_of_symbol = ();
%parent_lib_of_symbol = ();
%contained_obj = ();
%related_lib = ();
%obj_size = ();
%lib_size = ();
%region_obj_size = ();
%region_lib_size = ();
%region_contained_obj = ();
%region_obj = ();
%region_contained_lib = ();
@veneers = ();
%obj_pad = ();
%obj_lib_lookup = ();
$obj_pad_count = 0;
@pad = ();
%obj_debuginfo = ();
%lib_debuginfo = ();
%OBJ_RO_Size = ();
%LIB_RO_Size = ();
%OBJ_RW_Size = ();
%LIB_RW_Size = ();
%OBJ_ZI_Size = ();
%LIB_ZI_Size = ();
%region_OBJ_RO_Size = ();
%region_OBJ_RW_Size = ();
%region_OBJ_ZI_Size = ();
@sections = ();
%g_discard_symbols = ();
%symbol_info = ();
%symbol_lookup_table = ();
%region_arribution = ();
$g_fill = undef;
%g_fill_info = ();
}
sub ParseMAP
{
($g_MAPPath) = @_;
initGlobalVariable();
if(defined $g_MAPPath and -e $g_MAPPath)
{
open (FILE_HANDLE, "<$g_MAPPath") or &MAP_die("$g_MAPPath: file error!", __FILE__, __LINE__);
my ($strPreSymbolName, $strPreExeRegion, $strPreInputSection,$strSymbolName) = (undef, undef, undef, undef);
my ($flag_end_group, $b_enter_reference_table, $b_enter_discard) = (1, 0, 0);
#since $strPreInputSection will be set back to undef after _ParseContent(), we need another variable to store it
my ($strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName) = ("NOT_FOUND", undef, undef, undef, undef);
my $prefix = '(?:startup|unlikely)';#prefix of symbol, ex: .text.unlikely.UL1_SEND_MSG_TO_NVRAM
while (<FILE_HANDLE>)
{
my $strLine = $_;
if(/Discarded input sections/)
{
$b_enter_discard = 1; next;
}
elsif(/Memory Configuration/)
{
$b_enter_discard = 0; next;
}
elsif(/Memory map/)
{
$b_enter_discard = 0;
$flag_end_group = 0;
next;
}
elsif($b_enter_discard == 1)
{
$strPreSymbolName = _ParseDiscardInputSection($strLine, $strPreSymbolName);
}
elsif (/END GROUP/)
{
$flag_end_group = 0; next;
}
elsif ($flag_end_group)
{
next;
}
elsif (/Symbol\s+File/ or /Cross Reference Table/)
{ #Symbol File
$b_enter_reference_table = 1; next;
}
elsif($b_enter_reference_table == 0 )
{
if(/^(\S+)/ and $strLine !~/^OUTPUT\(/)
{#ignore: OUTPUT(./build/MT6589_MD2_TDD128HSPA/SKYPA/bin/MT6589_MD2_TDD128HSPA_PCB01_MT6589_S00.elf elf32-littlearm)
$strPreExeRegion = $1; next;
}
elsif(/^\s+(\.\b\w+\b)(\.\b$prefix\b)?(?:\.([^\.\s]+))?(\.\d+)?/)
{# .text.AsnDecode_RRC_BSIC => $strPreInputSection = .text; $strSymbolName = AsnDecode_RRC_BSIC
$strInputSectionName = $1;
$strSymbolName = ($4)?$3.$4:$3 if($3 or $4);
#if symbol name and size are in same line, need to parse symbol size
#.rodata.off 0x913f3760 0x1 ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatapi.obj)
next if ($strLine !~ /0x\w+/);
}
elsif(/^\s+(\S+)$/)
{# .debug_aranges
$strInputSectionName = $1; next;
}
elsif(/^\s+\*\*\s+merge\s+(\S+)$/)
{# ** merge strings
$strMergeName = $1; next
}
($strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName)
= _ParseContent($strLine, $strPreExeRegion, $strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName);
}
else
{
my $tmp_ref;
($strPreSymbolName,$tmp_ref) = _ParseSymboltable($_, $strPreSymbolName);
$parent_of_symbol{$strPreSymbolName}=$tmp_ref;
}
}
close FILE_HANDLE;
}
else
{
&MAP_die("MAP Path($g_MAPPath) doesn't exist", __FILE__, __LINE__);
}
}
sub _UpdateSize
{
my ($href, $strKey, $strSize) = @_;
if(exists $href->{$strKey})
{
$href->{$strKey} += hex($strSize);
}
else
{
$href->{$strKey} = hex($strSize);
}
}
sub _ParseDiscardInputSection
{
my ($strInput, $strPreLine) = @_;
chomp($strInput);
if($strInput =~ /^\s+(\S+)\s*$/)
{# .debug_aranges
# 0x0000000000000000 0x20 ./build/MT6589_MD2_TDD128HSPA/SKYPA/bin/lib/libsys_drv.a(bootarm_gcc.obj)
return $1;
}
elsif(/^\s+(0x\w+)/)
{
$strInput = $strPreLine . $strInput;
}
if (($strInput =~ /(\S+)\s+(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) ||
($strInput =~ /(\S+)\s+(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/))
{ # C$$code 0x0000000000000000 0x210 ./build/MT6572_DEMO_TDD128HSPA/DEFAULT/bin/lib/libsys_drv.a(bootarm_gcc.obj)
my $lib = $4;
my $obj = $5;
my $nSize = hex($3);
my $inputsection = $1;
_UpdateDiscardSymbol($inputsection, $nSize, $obj, $lib);
}
return "";
}
sub _UpdateDiscardSymbol
{
my ($inputsection, $nSize, $obj, $lib) = @_;
$g_discard_symbols{$obj.'$$'.$inputsection} = $nSize;
}
sub _ParseContent
{
my ($strInput, $strPreExeRegion, $strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName) = @_;
chomp($strInput);
## parse lib, obj, symbol size
if (($strInput =~ /\s+(\S+)?\s+(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) ||
($strInput =~ /\s+(\S+)?\s+(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/))
{
#**********************************************************
# For beloew three cases:
# Case1:symbol and addr in same line
# .rodata.off 0x913f3760 0x1 ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatapi.obj)
# Case2: symbol and addr in diff line
# .rodata.__FUNCTION__.108590
# 0x913f3764 0xb ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatceng.obj)
# Case3: contain input section
# EXTRAM_TXDATA 0x09e26864 0x63c8 ./mtk_rel/MT6297_EVB/NLWCTG_SAP/TARGET/lib//libgas_tdd.a(rlc_main.obj)
#**********************************************************
my $base = $2;
my $size = $3;
my $obj = $5;
$strLibName = $4;
$nInputSectionSize = hex($size);
$strObjName = $obj;
$strInputSectionName = $1 if ($1 and $1 !~ /\./);#case3:update input section.
$obj_pad{++$obj_pad_count} = $base;
$obj_lib_lookup{$base} = [$strObjName,$strLibName];
&ParseObjLib($strPreExeRegion, $strInput);
push(@sections, $strInputSectionName);
if($g_fill)
{
$g_fill_info{$base} = [$g_fill->[0], $g_fill->[1], , $region_arribution{$strPreExeRegion}, $obj, $strLibName];
$g_fill = undef;
}
_UpdateRORWZISize($strPreExeRegion, $base, $obj, $strLibName, $size);
}
elsif ($strInput =~ /(0x\w+)\s+(0x\w+)\s+linker stubs/)
{
&ParseObjLib($strPreExeRegion, $strInput);
_UpdateRORWZISize($strPreExeRegion, $1, "*stub*", undef, $2);
}
elsif(($strPreExeRegion =~ "EXTSRAM_L1DSP_ZI") and
(($strInput =~ /\*fill\*\s+(0x\w+)\s+(0x\w+)/) or ($strInput =~ /\*\*\s+zero\s+fill\s+(0x\w+)\s+(0x\w+)/)))
{
my $base = $1;
my $size = $2;
my $obj = "DSP";
$strLibName = "DSP";
$nInputSectionSize = hex($size);
$strObjName = $obj;
push(@sections, $strInputSectionName);
_UpdateRORWZISize($strPreExeRegion, $base, $obj, $strLibName, $size);
}
elsif(($strInput =~ /\*fill\*\s+(0x\w+)\s+(0x\w+)/) or ($strInput =~ /\*\*\s+zero\s+fill\s+(0x\w+)\s+(0x\w+)/))
{
$obj_pad{++$obj_pad_count} = $1;
push(@pad, $obj_pad_count);
#record fill info
$g_fill = [$1,hex($2)];
_UpdateRORWZISize($strPreExeRegion, $1, "*fill*", undef, $2);
}
elsif($g_fill && $strInput =~ /\s+(0x\w+)\s+(\S+\$\$\S+)\s+/)
{
#record fill info in hash table.
#there are same address for different linker symbols, in case get wrong info, here use address.symbol as the key of hash.
$g_fill_info{$1.".".$2} = [$g_fill->[0], $g_fill->[1], $region_arribution{$strPreExeRegion}, $2];
$g_fill = undef;
}
## parse symbol
if(!defined $strMergeName)
{
($strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize)
= _ParseSymbolInfo($strInput, $strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize);
}
## parse ** merge
if(defined $strMergeName)
{
if ($strInput =~ /^\s+(0x\w+)\s+(0x\w+)/)
{
$obj_pad{++$obj_pad_count} = $1;
push(@pad, $obj_pad_count);
_UpdateRORWZISize($strPreExeRegion, $1, "*$strMergeName*", undef, $2);
}
$strMergeName =undef;
}
return ($strObjName, $strLibName, $strInputSectionName, $nInputSectionSize, $strMergeName,$strSymbolName);
}
sub _UpdateRORWZISize
{
my ($strPreExeRegion, $base, $obj, $lib, $size) = @_;
$lib = $obj if(!defined $lib);
my $key = $strPreExeRegion."-".$obj;
my $objkey = $obj."-".$lib;
if($strPreExeRegion =~ /^\.debug/)
{
_UpdateSize(\%obj_debuginfo, $obj, $size);
_UpdateSize(\%lib_debuginfo, $lib, $size);
}
elsif(isZI($strPreExeRegion))
{
return if($base eq "0x0000000000000000");
_UpdateSize(\%OBJ_ZI_Size, $obj, $size);
_UpdateSize(\%LIB_ZI_Size, $lib, $size);
_UpdateSize(\%region_OBJ_ZI_Size, $key, $size);
_UpdateSize(\%obj_size, $objkey, $size);
$region_arribution{$strPreExeRegion} = "ZI";
}
elsif(isRW($strPreExeRegion))
{
return if($base eq "0x0000000000000000");
_UpdateSize(\%OBJ_RW_Size, $obj, $size);
_UpdateSize(\%LIB_RW_Size, $lib, $size);
_UpdateSize(\%region_OBJ_RW_Size, $key, $size);
_UpdateSize(\%obj_size, $objkey, $size);
$region_arribution{$strPreExeRegion} = "RW";
}
elsif(isRO($strPreExeRegion))
{
return if($base eq "0x0000000000000000" and $obj !~ /bootarm/i);
_UpdateSize(\%OBJ_RO_Size, $obj, $size);
_UpdateSize(\%LIB_RO_Size, $lib, $size);
_UpdateSize(\%region_OBJ_RO_Size, $key, $size);
_UpdateSize(\%obj_size, $objkey, $size);
$region_arribution{$strPreExeRegion} = "RO";
}
ParseInputSection($strPreExeRegion, $obj, $lib, $size);
}
sub isZI
{
my ($strRegionName) = @_;
my $bRet = ($strRegionName =~ /ZI|\.bss|EXTSRAM_DSP/);
return $bRet;
}
sub isRW
{
my ($strRegionName) = @_;
my $bRet = 0;
$bRet = 1 if(!isZI($strRegionName) and $strRegionName =~ /DSPRAM|EXTSRAM|DATA|RW/);
return $bRet;
}
sub isRO
{
my ($strRegionName) = @_;
my $bRet = 0;
$bRet = 1 if(!isZI($strRegionName) and !isRW($strRegionName)
and ($strRegionName !~/\.ARM\.attributes|\.comment|\.debug|\.stab/));
return $bRet;
}
#****************************************************************************
# subroutine: _ParseSymbolInfo
# input:
# output: N/A
#****************************************************************************
sub _ParseSymbolInfo
{
my ($strInput, $strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize) = @_;
my $skip_pattern = "Image\\$\\$|\\$\\$Base|\\$\\$Limit|\\$\\$Length|load address|\ LONG\ ";
if($strSymbolName and
(($strInput =~ /^\s+(?:\S+\s+)?(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) ||
($strInput =~ /^\s+(?:\S+\s+)?(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/)))
{ #for below case
# 0x911c5d06 0x214 ./mtk_rel/MT6297_EVB/NLWCTG_SAP/TARGET/lib/liburr_fdd.a(slce_configuration_controller.obj)
# .bss.fsm_desc 0x23c30ac4 0xec ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libatc.a(valatud.obj)
my $strAddress = $1;
my $symbol_lookup_key = $strSymbolName.".".$strObjName.".".$strLibName;
if($symbol_lookup_table{$symbol_lookup_key})
{
if($symbol_lookup_table{$symbol_lookup_key}->[1] > $strAddress)
{
delete $symbol_info{$symbol_lookup_table{$symbol_lookup_key}->[1].".".$strSymbolName};
}
else
{
$strAddress = $symbol_lookup_table{$symbol_lookup_key}->[1];
}
$nInputSectionSize += $symbol_lookup_table{$symbol_lookup_key}->[6];
}
$symbol_lookup_table{$symbol_lookup_key} = [$strSymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];
$symbol_info{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];
$strSymbolName = undef;
}
elsif($strInput =~ /^\s+(0x\w+)\s+(\w+)$/ and $strInput !~/$skip_pattern/)
{
# for below case
# 0x00024054 p_SLILM
my $strAddress = $1;
my $SymbolName = $2;
my $symbol_lookup_key = $SymbolName.".".$strObjName.".".$strLibName;
if(!$symbol_lookup_table{$symbol_lookup_key})
{# .bss 0x2443e1c0 0x20 ./build/MT6297_EVB/NLWCTG_SAP/bin/lib/libdevdrv.a(drv_mdcirq.obj)
# 0x2443e1c0 drv_mdcirq_activate_lisr_lock
$nInputSectionSize = hex(0);
$symbol_lookup_table{$symbol_lookup_key} = [$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];
$symbol_info{$strAddress.".".$SymbolName} = [$SymbolName, $strAddress, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize];
}
}
return ($strSymbolName, $strObjName, $strLibName, $strPreExeRegion, $strInputSectionName, $nInputSectionSize);
}
#****************************************************************************
# subroutine: _ParseSymboltable
# input: ($strInput, $strPreSymbolName)
# output: N/A
#****************************************************************************
sub _ParseSymboltable
{
my ($strInput, $strPreSymbolName) = @_;
if ($strInput =~ /(\S+)\s+.*[\/|\\](.*)\((.*)\)/)
{
$strPreSymbolName = $1;
my @lib_obj = [$2,$3];
my @obj_lib = [$3,$2];
push(@{$parent_of_symbol{$1}}, @lib_obj);
push(@{$parent_obj_of_symbol{$1}}, $3);
push(@{$parent_lib_of_symbol{$1}}, $2);
}
elsif ($strInput =~ /\s+.*[\/|\\](.*)\((.*)\)/)
{
my @lib_obj = [$1,$2];
my @obj_lib = [$2,$1];
push(@{$parent_of_symbol{$strPreSymbolName}}, @lib_obj);
push(@{$parent_obj_of_symbol{$strPreSymbolName}}, $2);
push(@{$parent_lib_of_symbol{$strPreSymbolName}}, $1);
}
return ($strPreSymbolName, $parent_of_symbol{$1} );
}
#****************************************************************************
# subroutine: ListAllSections
# input: N/A
# output: N/A
#****************************************************************************
sub ListAllSections
{
my %count;
my @uni_sections = grep { ++$count{ $_ } < 2; } @sections;
return \@uni_sections;
}
#****************************************************************************
# subroutine: ListAllLoadRegion (not support this function)
# input: N/A
# output: N/A
#****************************************************************************
sub ListAllLoadRegion
{
return undef;
}
#****************************************************************************
# subroutine: ListPadInfo
# input: N/A
# output: array reference
# for map file, array content:[array1,array2,...]
# array1:[strPadBaseAddress,[strPreObjName,strPreLibName],strPreObjAddress,[strPostObjName,strPostLibName],strPostObjAddress]
#****************************************************************************
sub ListPadInfo
{
my @padstring;
foreach my $temp(@pad)
{
my $pad_address = $obj_pad{$temp};
my $previous = $obj_pad{$temp - 1};
my $post = $obj_pad{$temp + 1};
my @pre_obj = $obj_lib_lookup{$previous};
my @post_obj = $obj_lib_lookup{$post};
# next if(!$pad_address);
my @padinfo = [$pad_address,@pre_obj,$previous,@post_obj,$post];
push (@padstring, @padinfo);
}
return \@padstring;
}
#****************************************************************************
# subroutine: StoreIntoTempFile
# input: N/A
# output: temp files which contain perl data structure
#****************************************************************************
use Storable qw/lock_nstore/;
sub StoreIntoTempFile
{
my ($strPath) = @_;
my $file = $strPath."\\MapParser_Temp.dat";
my %tempfile;
$tempfile{"parent_reference"} = \%parent_of_symbol;
$tempfile{"parent_obj_reference"} = \%parent_obj_of_symbol;
$tempfile{"parent_lib_reference"} = \%parent_lib_of_symbol;
$tempfile{"veneer"} = \@veneers;
$tempfile{"obj_in_exeregion"} = \%region_contained_obj;
$tempfile{"lib_in_exeregion"} = \%region_contained_lib;
$tempfile{"obj_by_lib"} = \%contained_obj;
$tempfile{"lib_by_obj"} = \%related_lib;
lock_nstore \%tempfile, $file;
}
#****************************************************************************
# subroutine: ParseObjLib
# input: Execution Region Name, $strLine
# output: N/A
#****************************************************************************
sub ParseObjLib
{
my ($strPreExeRegion, $strLine) = @_;
if (($strPreExeRegion !~ /\.ARM\.attributes/) and ($strPreExeRegion !~ /\.comment/)
and ($strPreExeRegion !~ /^\.debug/) and ($strPreExeRegion !~ /^\.stab/))
{
if ((/(0x\w+)\s+(0x\w+)\s+.*\\(.*)\((.*)\)/) || (/(0x\w+)\s+(0x\w+)\s+.*\/(.*)\((.*)\)/))
{
my $lib = $3;
my $obj = $4;
$contained_obj{$lib}{$obj} = 1;
$related_lib{$obj}{$lib} = 1;
}
elsif(/(0x\w+)\s+(0x\w+)\s+linker stubs/)
{## C$$code.stub 0x7000a258 0x8 linker stubs
push (@veneers, [$strPreExeRegion, $1, hex($2)]);
}
}
}
#****************************************************************************
# subroutine: ParseInputSection
# input: Execution Region Name, $strLine
# output: N/A
#****************************************************************************
sub ParseInputSection
{
my ($strExeRegionName, $obj, $lib, $size) = @_;
return if(!defined $strExeRegionName); ### setting for $strExeRegionName = undef
$region_contained_obj{$strExeRegionName}{$obj} = 1;
$region_contained_lib{$strExeRegionName}{$lib} = 1;
my $obj_key = $strExeRegionName."-".$obj."-".$lib;
my $lib_key = $strExeRegionName."-".$lib;
_UpdateSize(\%region_obj_size, $obj_key, $size);
_UpdateSize(\%region_lib_size, $obj_key, $size);
}
sub GetDiscardSymbol
{
my ($discard_href) = @_;
%$discard_href = %g_discard_symbols;
}
#****************************************************************************
# subroutine: GetSymbolInfo
# input:
#
#****************************************************************************
sub GetSymbolInfo
{
my ($symbol_key) = @_;
my @symbol_info_array = @{$symbol_info{$symbol_key}} if $symbol_info{$symbol_key};
return @symbol_info_array;
}
#****************************************************************************
# subroutine: GetFillInfo
# input:
#
#****************************************************************************
sub GetFillInfo
{
return \%g_fill_info;
}
#****************************************************************************
# subroutine: GetParentOfSymbol
# input: Execution Region Name, flag (all/lib/obj)
# output: (Object Name, Library Name) which refers to given symbol (flag = all)
# Object Name which refers to given symbol (flag = obj)
# Library Name which refers to given symbol (flag = lib)
#****************************************************************************
sub GetParentOfSymbol
{
# Name Size VMA LMA File off Algn
my ($strSymName, $flag) = @_;
my $parent_array;
if($flag eq "all")
{
$parent_array = $parent_of_symbol{$strSymName};
}
elsif($flag eq "lib")
{
$parent_array = $parent_lib_of_symbol{$strSymName};
}
elsif($flag eq "obj")
{
$parent_array = $parent_obj_of_symbol{$strSymName};
}
return $parent_array;
}
#****************************************************************************
# subroutine: GetChildOfSymbol
# input: symbol name
# output: undef(not support this function)
#****************************************************************************
sub GetChildOfSymbol
{
my ($strSymbolName) = @_;
return undef;
}
#****************************************************************************
# subroutine: ListObjByLib
# input: Library Name
# output: Objects array reference
#****************************************************************************
sub ListObjByLib
{
my ($lib_name) = @_;
my @obj_array = keys %{$contained_obj{$lib_name}};
return \@obj_array;
}
#****************************************************************************
# subroutine: ListLibByObj
# input: Object Name
# output: Library array reference
#****************************************************************************
sub ListLibByObj
{
my ($obj_name) = @_;
my @lib_array = keys %{$related_lib{$obj_name}};
return \@lib_array;
}
#****************************************************************************
# subroutine: ListObjLibByAddr
# input: symbol address
# output: objeck and lib info
#****************************************************************************
sub ListObjLibByAddr
{
my ($strAddress) = @_;
my @obj_lib_by_addr = @{$obj_lib_lookup{$strAddress}} if $obj_lib_lookup{$strAddress};
return \@obj_lib_by_addr;
}
#****************************************************************************
# subroutine: GetTotalSizeByObj
# input: Object Name, Library Name
# output: Total size of given object
# (excluding size in .comment, .ARM.attribut,
# execution region which begins with .debug or .stab)
#****************************************************************************
sub GetTotalSizeByObj
{
my ($obj_name, $lib_name) = @_;
my $key = $obj_name."-".$lib_name;
my $obj_size = $obj_size{$key};
return $obj_size;
}
#****************************************************************************
# subroutine: GetTotalSizeByLib
# input: Library Name
# output: Total size of given library
# (excluding size in .comment, .ARM.attribut,
# execution region which begins with .debug or .stab)
#****************************************************************************
sub GetTotalSizeByLib
{
my ($lib_name) = @_;
my $obj_array = $contained_obj{$lib_name};
foreach my $temp (@$obj_array)
{
my $strObjSize = CommonUtil::Dec2Hex($obj_size{$temp});
_UpdateSize(\%lib_size, $lib_name, $strObjSize);
}
return $lib_size{$lib_name};
}
#****************************************************************************
# subroutine: GetObjByExeRegion
# input: Execution Region Name
# output: objects which given execution region contains
#****************************************************************************
sub GetObjByExeRegion
{
my ($strExeRegionName) = @_;
my @obj_array = keys %{$region_contained_obj{$strExeRegionName}};
return \@obj_array;
}
#****************************************************************************
# subroutine: GetLibByExeRegion
# input: Execution Region Name
# output: libraries which given execution region contains
#****************************************************************************
sub GetLibByExeRegion
{
my ($strExeRegionName) = @_;
my @lib_array = keys %{$region_contained_lib{$strExeRegionName}};
return \@lib_array;
}
#****************************************************************************
# subroutine: GetObjSizeByExeRegion
# input: ExeRegion Name, Object Name, Library Name
# output: size of object in given execution region
#****************************************************************************
sub GetObjSizeByExeRegion
{
my ($strExeRegion, $strObj, $strLib) = @_;
my $string = $strExeRegion."-".$strObj."-".$strLib;
my $obj_size = $region_obj_size{$string};
return $obj_size;
}
#****************************************************************************
# subroutine: GetLibSizeByExeRegion
# input: ExeRegion Name, Library Name
# output: size of library in given execution region
#****************************************************************************
sub GetLibSizeByExeRegion
{
my ($strExeRegion, $strLib) = @_;
my $string = $strExeRegion."-".$strLib;
my $lib_size = $region_lib_size{$string};
return $lib_size;
}
#****************************************************************************
# subroutine: GetObjSizeByCatExeRegion
# input: $strRegionName: Execution Name (Case sensitive)
# $strCategory: RO/RW/ZI (Case sensitive)
# output: ObjCateSize Hash Reference
#****************************************************************************
sub GetObjSizeByCatExeRegion
{
my ($strERName, $strCategory) = @_;
my %ObjSize; # {strObjName} => Size
my $included_obj_aref = &GetObjByExeRegion($strERName);
my $region_OBJ_href = undef;
$region_OBJ_href = \%region_OBJ_ZI_Size if(isZI($strERName) and $strCategory =~ /ZI/i);
$region_OBJ_href = \%region_OBJ_RW_Size if(isRW($strERName) and $strCategory =~ /RW/i);
$region_OBJ_href = \%region_OBJ_RO_Size if(isRO($strERName) and $strCategory =~ /RO/i);
if(defined $region_OBJ_href)
{
foreach my $temp(@$included_obj_aref)
{
my $key = $strERName."-".$temp;
if(exists $region_OBJ_href->{$key})
{
$ObjSize{$temp} = $region_OBJ_href->{$key};
}
else
{
$ObjSize{$temp} = 0;
}
}
}
return \%ObjSize;
}
#****************************************************************************
# subroutine: GetVeneerInfo
# input: N/A
# output: [Execution Region, Base Address, Size] list for veneer
#****************************************************************************
sub GetVeneerInfo
{
return \@veneers;
}
#****************************************************************************
# subroutine: GetExeRegionAttr
# input: N/A
# output: {region_name} = region attribution
#****************************************************************************
sub GetExeRegionAttr
{
return \%region_arribution;
}
#****************************************************************************
# subroutine: ListObjLibBySymbol
# input: $strSymName: Symbol Name (Case sensitive)
# output: for map file, output array reference
# array content:[[strObjName1,strLibName1],[strObjName2,strLibName2],...]
#****************************************************************************
sub ListObjLibBySymbol
{
print "[Error] not support any more\n";
return undef;
}
#****************************************************************************
# subroutine: GetLoadRegionInfo - Get Load Region information
# input: N/A
# output: undef(not support this function)
#****************************************************************************
sub GetLoadRegionInfo
{
return undef;
}
#****************************************************************************
# subroutine: GetTotalROSize - Get total RO size
# input: $bNeedString: 1=Return string, 0/default/no input=Return int
# output: undef(not support this function)
#****************************************************************************
sub GetTotalROSize
{
my ($bNeedString) = @_;
return undef;
}
#****************************************************************************
# subroutine: GetTotalRWZISize - Get total RWZI size
# input: $bNeedString: 1=Return string, 0/default/no input=Return int
# output: undef(not support this function)
#****************************************************************************
sub GetTotalRWZISize
{
my ($bNeedString) = @_;
return undef;
}
#****************************************************************************
# subroutine: GetTotalROMSize - Get total ROM size
# input: $bNeedString: 1=Return string, 0/default/no input=Return int
# output: undef(not support this function)
#****************************************************************************
sub GetTotalROMSize
{
my ($bNeedString) = @_;
return undef;
}
#****************************************************************************
# subroutine: GetObjDebugInfoSize
# input: $strObjName: Obj Name (Case sensitive)
# output: debug info size for given obj
#****************************************************************************
sub GetObjDebugInfoSize
{
my ($strObjName) = @_;
my $DebugInfoSize = $obj_debuginfo{$strObjName};
return $DebugInfoSize;
}
#****************************************************************************
# subroutine: ListObjSummaryInfo
# input: obj name, flag represents which column to show
# flag = "RO"
# = "RW"
# = "ZI"
# = "Debug"
# output: RO/RW/ZI/Debug size for given obj
#****************************************************************************
sub ListObjSummaryInfo
{
my ($strName, $flag) = @_;
my $nSize = 0;
if ($flag =~ /RO/i)
{
$nSize = $OBJ_RO_Size{$strName};
}
elsif ($flag =~ /RW/i)
{
$nSize = $OBJ_RW_Size{$strName};
}
elsif ($flag =~ /ZI/i)
{
$nSize = $OBJ_ZI_Size{$strName};
}
elsif ($flag eq "Debug")
{
$nSize = $obj_debuginfo{$strName};
}
return $nSize;
}
#****************************************************************************
# subroutine: ListLibSummaryInfo
# input: lib name, flag represents which column to show
# flag = "RO"
# = "RW"
# = "ZI"
# = "Debug"
# output: RO/RW/ZI/Debug size for given lib
#****************************************************************************
sub ListLibSummaryInfo
{
my ($strLibName, $flag) = @_;
my $nSize = 0;
if ($flag =~ /RO/i)
{
$nSize = $LIB_RO_Size{$strLibName};
}
elsif ($flag =~ /RW/i)
{
$nSize = $LIB_RW_Size{$strLibName};
}
elsif ($flag =~ /ZI/i)
{
$nSize = $LIB_ZI_Size{$strLibName};
}
elsif ($flag eq "Debug")
{
$nSize = $lib_debuginfo{$strLibName};
}
return $nSize;
}
#****************************************************************************
# subroutine: GrepSymbolByInputSection
# input: input section name represent in regular expression
# ex: INTSRAM_ROCODE.*
# INTSRAM_ROCODE_A
# INTSRAM_ROCODE_B
#
# output: symbol info array reference in order of address in the following format:
# [[$strSymbolName, $nSymbolAddr, $strObjName, $strLibName, $strOutputSectionName, $strInputSectionName, $nInputSectionSize], ...]
#****************************************************************************
sub GrepSymbolByInputSection
{
my ($strSectionNameInRegularExp) = @_;
my @SymInfoKeys = sort { hex($symbol_info{$a}->[SymbolInfoTable::Addr]) <=> hex($symbol_info{$b}->[SymbolInfoTable::Addr]) }
grep{$symbol_info{$_}->[SymbolInfoTable::InputSectionName] =~ /$strSectionNameInRegularExp/} keys %symbol_info;
#map {print $_."\n"} @SymInfoKeys;
my @SymInfo = map {$symbol_info{$_}} @SymInfoKeys;
return \@SymInfo;
}
#****************************************************************************
# subroutine: GrepSymbolByOutputSection
# input: input section name represent in regular expression
# ex: CACHED_EXTSRAM_L2CACHE_LOCK_DATA
# CACHED_EXTSRAM_L2CACHE_LOCK_DATA
# CACHED_EXTSRAM_L2CACHE_LOCK_DATA_ZI
#
# output: symbol info array reference in order of address in the following format:
# [[$strObjName, $strLibName], [$strObjName, $strLibName] ...]
#****************************************************************************
sub GrepSymbolByOutputSection
{
my ($strSectionNameInRegularExp) = @_;
my @SymInfoKeys = sort { hex($symbol_info{$a}->[SymbolInfoTable::Addr]) <=> hex($symbol_info{$b}->[SymbolInfoTable::Addr]) }
grep{$symbol_info{$_}->[SymbolInfoTable::OutputSectionName] =~ /$strSectionNameInRegularExp/} keys %symbol_info;
#map {print $_."\n"} @SymInfoKeys;
my @SymInfo = map {$symbol_info{$_}} @SymInfoKeys;
return \@SymInfo;
}