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