#!/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; | |
} | |