| #!/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: |
| #* --------- |
| #* FileInfoParser.pm |
| #* |
| #* Project: |
| #* -------- |
| #* |
| #* |
| #* Description: |
| #* ------------ |
| #* This module collects the subroutines for common utility. |
| #* |
| #* |
| #* Author: |
| #* ------- |
| #* Carl Kao (mtk08237) |
| #* |
| #****************************************************************************/ |
| |
| use strict; |
| BEGIN{push(@INC,'../', './tools/', './tools/MemoryUtility/')}; |
| use CommonUtility; |
| use Digest::MD5; |
| |
| package Region; |
| use constant Size => 1; |
| use constant VMA => 2; |
| use constant LMA => 3; |
| use constant Offsets => 4; |
| use constant Align => 5; |
| use constant Attr => 6; |
| |
| # for %g_SymTable = (); |
| package SymTable; |
| use constant Name => 0; |
| use constant Addr => 1; |
| use constant Group => 2; |
| use constant Region => 3; |
| use constant Size => 4; |
| use constant Obj => 5; |
| use constant NeedMerge => 6; |
| |
| # for %symbol = (); |
| package Symbol; |
| use constant Addr => 0; |
| use constant Region => 3; |
| use constant Size => 4; |
| |
| # for %g_LinkerSymbol = (); |
| package LinkerSymbol; |
| use constant Addr => 0; |
| use constant Group => 1; |
| use constant Region => 2; |
| use constant Size => 3; |
| |
| package LinkerSymPostfix; |
| use constant Base => 0; |
| use constant Limit => 1; |
| use constant ZIBase => 2; |
| use constant ZILimit => 3; |
| use constant Length => 4; |
| use constant ZILength => 5; |
| |
| package LinkerSymPrefix; |
| use constant Image => 0; |
| use constant Load => 1; |
| use constant None => 2; |
| |
| #**************************************************************************** |
| # Constants |
| #**************************************************************************** |
| my $SYM_FILE_PARSER_VERNO = " u0.07"; |
| # u0.07 , 2015/10/28, Carl, Support LinkerSymPostfix::ZILength |
| # u0.06 , 2015/01/22, Carl, Add parsing rule for GCC 4.9.3 |
| # u0.05 , 2015/01/19, Carl, Memory Utility Refinement |
| # u0.04, 2014/09/26, Carl, Add constant for LinkerSymPrefix |
| # u0.03, 2014/09/16, Carl, Add parsing rule for GCC 4.9.2 |
| # u0.02, 2014/03/03, BM, Refine inculde path |
| # u0.01, 2014/02/20, BM, Init version, branch from MOLY |
| |
| #**************************************************************************** |
| # Global variable |
| #**************************************************************************** |
| package SymFileParser; |
| |
| my $g_SYMPath; |
| my %symbol; |
| my $DUMMY_END_size; |
| my $DUMMY_END_base; |
| my %g_SymTable; # $strAddress.$strSymbolName => [strSymbol, $strAddress, strGroup, strRegion, nSize] |
| my %g_LinkerSymbol; # $strSymbolName => [$strAddress, strGroup, strRegion, nSize] |
| my %g_static_symbol_loookup; #$strSymbolName.".".$strObjName = [$strAddress, strGroup, strRegion, nSize] |
| |
| my $g_PreviousParsedSYMChecksum; |
| my $g_PreviousParsedSYMPath; |
| |
| my %g_ExeRegion;# Execution Region |
| my %g_ExeRegionLookUpTable; # RegionName -> Index |
| my %Attr; |
| |
| #**************************************************************************** |
| # oo >>> Finished |
| #**************************************************************************** |
| return 1; |
| |
| #**************************************************************************** |
| # subroutine: SYM_die |
| # sample code: (message, __FILE__, __LINE__) |
| # input: $error_msg, $file, $line_no |
| #**************************************************************************** |
| sub SYM_die |
| { |
| my ($error_msg, $file, $line_no) = (@_); |
| &CommonUtil::error_handler($error_msg, $file, $line_no, 'SYM'); |
| } |
| |
| #**************************************************************************** |
| # subroutine: ParseSYM |
| # input: SYM Path string |
| # output: x |
| #**************************************************************************** |
| sub Clean |
| { |
| %symbol = (); |
| %g_ExeRegion = (); |
| %g_ExeRegionLookUpTable = (); |
| %g_SymTable = (); |
| %g_LinkerSymbol = (); |
| %Attr = (); |
| $DUMMY_END_size = 0; |
| $DUMMY_END_size = 0; |
| } |
| |
| sub ParseSYM |
| { |
| ($g_SYMPath) = (@_); |
| if(defined $g_SYMPath and -e $g_SYMPath) |
| { |
| open (my $fh, '<', $g_SYMPath) or &SYM_die("$g_SYMPath: file error!", __FILE__, __LINE__); |
| binmode ($fh); |
| my $SYMChecksum = Digest::MD5->new->addfile($fh)->hexdigest; |
| |
| if($g_SYMPath eq $g_PreviousParsedSYMPath and $SYMChecksum eq $g_PreviousParsedSYMChecksum) |
| { |
| #print "Sym File: $g_SYMPath was parsed before and not modified, skip PasrseSYM\n"; |
| close($fh); |
| return; |
| } |
| close($fh); |
| |
| Clean(); |
| open (FILE_HANDLE, "<$g_SYMPath") or &SYM_die("$g_SYMPath: file error!", __FILE__, __LINE__); |
| my $strPreExeRegionName = undef; |
| my $bBegin = 0; #0= Program Header: begin, 1= Sections begin, 2=SYMBOL TABLE: begin |
| my $strObjName = undef; #parse static symbol's obj |
| |
| while (<FILE_HANDLE>) |
| { |
| my $strLine = $_; |
| $bBegin = 1 if($strLine =~/^Sections:$/);#begin parse section table |
| $bBegin = 2 if($strLine =~/^SYMBOL TABLE:$/);#begin parse symbol table |
| |
| if ($strLine =~ /\.hidden\s/) |
| { |
| $strObjName = undef;#no static symbol after '.hidden' |
| |
| # add this rule for GCC 4.9.3 |
| # [4.9.2] a0401ee4 g O CACHED_EXTSRAM 00000008 .hidden __CTOR_LIST__ |
| $strLine =~ s|\.hidden\s||g; |
| } |
| |
| last if($strLine =~/^RELOCATION RECORDS FOR \[ROM\]:$/); |
| |
| ## begin to parse section table |
| if ($bBegin == 1 and |
| $strLine =~ /\s*(\d+)\s+(\S+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\S+)/) |
| { # Idx Name Size VMA LMA File off Algn |
| # 0 BL_GFH_SECTION 00000170 7000a000 7000a000 00002000 2**2 |
| $g_ExeRegion{$1}= [$2, $3, $4, $5, $6, $7]; |
| $g_ExeRegionLookUpTable{$2} = $1; |
| $strPreExeRegionName = $2; |
| next; |
| } |
| elsif($bBegin == 1 and defined $strPreExeRegionName) |
| { #parse section attribution |
| &ParseInputSection($strPreExeRegionName, $strLine); |
| next; |
| } |
| |
| ## begin to parse symbol table |
| $strObjName = ParseSymbolTable($strLine,$strObjName) if($bBegin == 2); |
| |
| if ($bBegin ==2 and $strLine =~ /DUMMY_END\$\$Base/) |
| { # f3fc0000 g *ABS* 00000000 Image$$CACHED_DUMMY_END$$Base |
| |
| if(/^(\w+)\s+(\w+)\s+(.*)\s+(\w+)/) |
| { |
| $DUMMY_END_size = hex($4); |
| $DUMMY_END_base = "0x".$1; |
| } |
| next; |
| } |
| elsif ($bBegin ==2 and |
| $strLine =~ /^(\w+)\s+(\w+)\s+(\w+)\s+(\S+)\s+(\w+)\s+(\w+)$/) |
| { # 7000a000 l d BL_GFH_SECTION 00000000 BL_GFH_SECTION |
| next if (($2 ne "g") && ($2 ne "l") && ($2 ne "w")); |
| next if (($3 ne "F") && ($3 ne "O")); |
| my $symbol_name = $6; |
| my $base_address = $1; |
| my $execution_region = $4; |
| my $size = $5; |
| $symbol{$symbol_name} = [$1, $2, $3, $4, $5]; |
| next; |
| } |
| elsif ($bBegin ==2 and |
| $strLine =~ /^(\w+)\s+(\w+)\s+(\w+)\s+(\S+)\s+(\w+)\s+(\w+)\s+(\w+)$/) |
| { # 901c2ae8 g F ROM 00000048 0xf0 EL1D_LPWR_Other_Core_Has_Run_Determine |
| next if (($2 ne "g") && ($2 ne "l") && ($2 ne "w")); |
| next if (($3 ne "F") && ($3 ne "O")); |
| my $symbol_name = $7; |
| my $base_address = $1; |
| my $execution_region = $4; |
| my $size = $5; |
| $symbol{$symbol_name} = [$1, $2, $3, $4, $5]; |
| next; |
| } |
| |
| } |
| close FILE_HANDLE; |
| &FixInputSectionLMAValue(); |
| |
| #record parsed sym file path and file checksum |
| $g_PreviousParsedSYMPath = $g_SYMPath; |
| $g_PreviousParsedSYMChecksum = $SYMChecksum; |
| } |
| else |
| { |
| &SYM_die("SYM Path($g_SYMPath) doesn't exist", __FILE__, __LINE__); |
| } |
| } |
| |
| sub ParseSymbolTable |
| { |
| my ($strLine,$strObjName) = @_; |
| my $bSearched = 0; |
| my ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize); |
| |
| if($strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+.+\\(\S+)\./ |
| ||$strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+.+\/(\S+)\./) |
| { #parse file name |
| #00000000 l df *ABS* 00000000 protocol/as_multimode/dbme/src/db_io.c |
| $strObjName = $2.".obj"; |
| } |
| elsif($strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+(\S+)\./) |
| { #parse file name |
| #00000000 l df *ABS* 00000000 db_io.c |
| $strObjName = $2.".obj"; |
| } |
| elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\S+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/) |
| {#90338508 g F ROM 0000002e 0xf0 FT_GetDiskFreeSpace |
| ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($7, "0x".$1, $2.$3, $4, hex($5)); |
| $bSearched = 1; |
| } |
| elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/) |
| {#0001622c l F ROM 000001b4 ast_hif_mcu_lisr_handler |
| ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($6, "0x".$1, $2.$3, $4, hex($5)); |
| $bSearched = 1; |
| } |
| elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/) |
| {#90004200 l ROM 00000000 IRQ0_VEC |
| ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($5, "0x".$1, $2, $3, hex($4)); |
| $bSearched = 1; |
| } |
| elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\S+\$\$\S+)$/) |
| {#f06185f1 g CACHED_EXTSRAM 00000000 BUILD_TIME_RW$$Base |
| ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($5, "0x".$1, $2, $3, hex($4)); |
| $bSearched = 1; |
| } |
| |
| if($bSearched) |
| { |
| if($strGroup ne "l" and $strGroup ne "ldf" and $strGroup ne "ld") |
| {#skip 00000000 l *ABS* 00000000 MT6589 |
| #skip 00000000 l df *ABS* 00000000 ft_fnc_fat.c |
| |
| ## parse linker symbol |
| if($strSymbolName =~ /\$\$/ and (($strGroup eq "g") or ($strGroup eq "w"))) |
| { |
| $g_LinkerSymbol{$strSymbolName} = [$strAddress, $strGroup, $strRegion, $nSize]; |
| } |
| |
| ##parse static symbol |
| elsif($strObjName and (($strGroup eq "lO") or ($strGroup eq "lF"))) |
| { |
| #****************************************** |
| # Static symbol need to be merged |
| # |
| # Before merge: |
| # 900bcdf0 l F ROM 00000230 ssleay_rand_add.part.0 |
| # 900bd020 l F ROM 00000008 ssleay_rand_add |
| # |
| # After merge: |
| # 900bcdf0 l F ROM 00000238 ssleay_rand_add |
| #****************************************** |
| |
| my $need_merge = ($strLine=~/\.part\./)?1:0; |
| |
| if($g_static_symbol_loookup{$strSymbolName.".".$strObjName} && ($need_merge || $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::NeedMerge])) |
| { |
| if($g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Addr] <= $strAddress) |
| { |
| $strAddress = $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Addr]; |
| } |
| else |
| { |
| delete $g_SymTable{$strAddress.".".$strSymbolName}; |
| } |
| |
| $nSize += $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Size]; |
| $g_static_symbol_loookup{$strSymbolName.".".$strObjName} = [$strSymbolName,$strAddress, $strGroup, $strRegion, $nSize, $strObjName, $need_merge]; |
| $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName]; |
| } |
| else |
| { |
| $g_static_symbol_loookup{$strSymbolName.".".$strObjName} = [$strSymbolName,$strAddress, $strGroup, $strRegion, $nSize, $strObjName, $need_merge]; |
| $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName]; |
| } |
| } |
| ## parse global symbol |
| else |
| { |
| print "$strAddress.$strSymbolName appears before\n" if(exists $g_SymTable{$strAddress.".".$strSymbolName}); |
| $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize]; |
| } |
| } |
| elsif($strGroup eq "l" && $strSymbolName =~ /\$\$/) |
| {# add this rule for GCC 4.9.2 |
| # 01400000 l L1CORE_RWZI 00000000 Image$$L1CORE_RWZI$$ZI$$Base |
| $g_LinkerSymbol{$strSymbolName} = [$strAddress, $strGroup, $strRegion, $nSize]; |
| } |
| } |
| return $strObjName; |
| } |
| |
| #**************************************************************************** |
| # subroutine: GetSymbolTable |
| # input: N/A |
| # output: get all symbol table in .sym file |
| # |
| #**************************************************************************** |
| sub GetSymbolTable |
| { |
| my @symbol = values %g_SymTable; |
| return \@symbol; |
| } |
| |
| #**************************************************************************** |
| # subroutine: GetSymbol |
| # input: N/A |
| # output: get all symbol info in .sym file |
| # NOTE: The info for global symbol is right; |
| # but for static symbol which has same name with other symbol, the info maybe wrong. |
| #**************************************************************************** |
| sub GetSymbol |
| { |
| return \%symbol; |
| } |
| |
| sub GetLinkerSymbol |
| { |
| return \%g_LinkerSymbol; |
| } |
| |
| sub GrepSymbolBySection |
| { |
| my ($strSection) = @_; |
| my @SymKeys = sort { hex($g_SymTable{$a}->[SymTable::Addr]) <=> hex($g_SymTable{$b}->[SymTable::Addr]) } |
| grep{$g_SymTable{$_}->[SymTable::Region] eq $strSection} keys %g_SymTable; |
| #map {print $_."\n"} @SymKeys; |
| my @SymInfo = map {$g_SymTable{$_}} @SymKeys; |
| return \@SymInfo; |
| } |
| |
| sub GrepSymbolByOutputSection |
| { |
| my ($strSection) = @_; |
| my $strStart = GetLinkerSymbolAddress($strSection, LinkerSymPostfix::Base, LinkerSymPrefix::Image); |
| my $strEnd = GetLinkerSymbolAddress($strSection, LinkerSymPostfix::ZILimit, LinkerSymPrefix::Image); |
| my @SymInfo; |
| |
| if((hex($strEnd) - hex($strStart)) > 0) |
| { |
| my @SymKeys = sort { hex($g_SymTable{$a}->[SymTable::Addr]) <=> hex($g_SymTable{$b}->[SymTable::Addr]) } |
| grep{(hex($g_SymTable{$_}->[SymTable::Addr]) >= hex($strStart)) and |
| (hex($g_SymTable{$_}->[SymTable::Addr]) < hex($strEnd ))} keys %g_SymTable; |
| @SymInfo = map {$g_SymTable{$_}} @SymKeys; |
| } |
| return \@SymInfo; |
| } |
| |
| #**************************************************************************** |
| # subroutine: GetLinkerSymbolAddress |
| # input: $strRegionName, $nLocation, $nRegionType |
| # output: $strAddr |
| # NOTE: |
| # nRegionType = 0: Execution Region |
| # nRegionType = 1: Load Region |
| # nRegionType = 2: Input Section |
| #**************************************************************************** |
| sub GetLinkerSymbolAddress |
| { |
| my ($strRegionName, $nLocation, $nRegionType) = @_; |
| my $strPrefix = 'Image$$'; |
| if($nRegionType == 1) |
| { |
| $strPrefix = 'Load$$' ; |
| $nLocation = 0; |
| } |
| elsif($nRegionType == 2) |
| { |
| $strPrefix = ""; |
| } |
| my $strPostfix = '$$Base'; #LinkerSymPostfix::Base |
| $strPostfix = '$$Limit' if($nLocation == LinkerSymPostfix::Limit); |
| $strPostfix = '$$ZI$$Base' if($nLocation == LinkerSymPostfix::ZIBase); |
| $strPostfix = '$$ZI$$Limit' if($nLocation == LinkerSymPostfix::ZILimit); |
| $strPostfix = '$$Length' if($nLocation == LinkerSymPostfix::Length); |
| $strPostfix = '$$ZI$$Length'if($nLocation == LinkerSymPostfix::ZILength); |
| my $strSymbolName = $strPrefix.uc($strRegionName).$strPostfix; |
| my $strAddr = undef; |
| $strAddr = $g_LinkerSymbol{$strSymbolName}->[0] if(exists $g_LinkerSymbol{$strSymbolName}); |
| return $strAddr; |
| } |
| |
| #**************************************************************************** |
| # subroutine: Get_DUMMY_END_Size |
| # input: N/A |
| # output: size of DUMMY_END region |
| #**************************************************************************** |
| sub Get_DUMMY_END_Size |
| { |
| return $DUMMY_END_size; |
| } |
| |
| #**************************************************************************** |
| # subroutine: Get_DUMMY_END_Base |
| # input: N/A |
| # output: base address of DUMMY_END region |
| #**************************************************************************** |
| sub Get_DUMMY_END_Base |
| { |
| return $DUMMY_END_base; |
| } |
| |
| #**************************************************************************** |
| # 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."\\SymParser_Temp.dat"; |
| my %tempfile; |
| |
| $tempfile{"execution_region"} = \%g_ExeRegion; |
| $tempfile{"symbol_info"} = \%symbol; |
| |
| lock_nstore \%tempfile, $file; |
| } |
| |
| #**************************************************************************** |
| # subroutine: ParseInputSection. used by ParseSYM to parse Execution Region Attribute |
| # input: 1. Execution Name, 2. $strLine |
| # output: x |
| #**************************************************************************** |
| sub ParseInputSection |
| { |
| my ($strExeRegionName, $strLine) = @_; |
| return if(!defined $strExeRegionName);#setting for $strExeRegionName = undef |
| |
| my $attr = undef; |
| chomp($strLine); |
| if($strLine =~ /\s+(.*)/) |
| { |
| #CONTENTS, ALLOC, LOAD, READONLY, DATA |
| $Attr{$strExeRegionName} = $1; |
| } |
| } |
| |
| #**************************************************************************** |
| # subroutine: FixInputSectionLMAValue is used to fix the wrong LMA value |
| # record in InputSection |
| # input: x |
| # output: x |
| #**************************************************************************** |
| sub FixInputSectionLMAValue |
| { |
| while(my($strSymbolName, $arySymbolDataRef) = each %g_LinkerSymbol) |
| { |
| my @arySymbolData = @$arySymbolDataRef;# arySymbolData: 0x00760eb0 g *ABS* 0 |
| #print "arySymbolData: @arySymbolData \n"; |
| if($strSymbolName =~ /Load\$\$(\S+)\$\$Base/)# $strSymbolName = Load$$EXTSRAM_DSP_RX$$Base |
| {# Load$$EXTSRAM_DSP_RX$$Base |
| my $strExeRegionName = $1;# $strExeRegionName = EXTSRAM_DSP_RX |
| |
| #check if $strExeRegionName exist in $g_ExeRegionLookUpTable |
| if(exists $g_ExeRegionLookUpTable{$strExeRegionName}) |
| { |
| #extract the correct LMA value record in SymbolTable |
| my $strCorrectLMAValue = $arySymbolData[LinkerSymbol::Addr]; |
| $strCorrectLMAValue =~ s/0x//; |
| #print "strCorrectLMAValue: $strCorrectLMAValue \n"; |
| |
| #fix LMA value stored in %g_ExeRegion |
| my $lookupIndex = $g_ExeRegionLookUpTable{$strExeRegionName}; |
| #print "look up index: ".$lookupIndex."\n"; |
| $g_ExeRegion{$lookupIndex}[Region::LMA] = $strCorrectLMAValue; |
| } |
| } |
| } |
| } |
| |
| #**************************************************************************** |
| # subroutine: ListAllExeRegion |
| # input: $bTrimDebugRegion: 1= NeedtoTrimDebugRegion, 0 or undef=NoNeedToTrimDebugRegion |
| # output: Execution Region List |
| #**************************************************************************** |
| sub ListAllExeRegion |
| { |
| my ($bTrimDebugRegion) = @_; |
| my @k = keys %g_ExeRegion; |
| my @ExeRegion; |
| my $ExeRegion_aref = undef; |
| for (my $i = 0; $i <= $#k; $i++) |
| { |
| push(@ExeRegion,$g_ExeRegion{$i}->[0]); |
| } |
| $ExeRegion_aref = \@ExeRegion; |
| if($bTrimDebugRegion) |
| { |
| $ExeRegion_aref = TrimDebugRegion(\@ExeRegion); |
| } |
| return $ExeRegion_aref; |
| } |
| #**************************************************************************** |
| # subroutine: TrimDebugRegion |
| # input: All Regions in array reference |
| # output: Execution Region List(array reference) after trimming |
| #**************************************************************************** |
| sub TrimDebugRegion |
| { |
| my ($ERs_aref) = @_; |
| my @RealERs; |
| foreach my $region (@$ERs_aref) |
| { |
| if ( $region !~ /^\.debug_/ |
| and $region !~ /^\.ARM\.attributes/ |
| and $region !~ /^\.comment/ |
| and $region !~ /^\.stab/ |
| and $region ne "") |
| { |
| push(@RealERs , $region); |
| } |
| } |
| return \@RealERs; |
| } |
| |
| #**************************************************************************** |
| # subroutine: GetExeRegionInfo |
| # input: Execution Region Name, $nOption |
| # $nOption = Region::VMA or Region::LMA or Region::Size |
| # or Region::Offsets or Region::Align or Region::Attr |
| # output: string of corresponding Execution Region Infomation |
| #**************************************************************************** |
| sub GetExeRegionInfo |
| { |
| # Name Size VMA LMA File off Algn |
| my ($strExeRegionName, $nOption) = @_; |
| my $index = $g_ExeRegionLookUpTable{$strExeRegionName}; |
| my @ExeRegionInfo; |
| my $strInfo; |
| my @k = keys %g_ExeRegion; |
| my $key_count = $#k + 1; |
| for (my $i = 0; $i <= $#k; $i++) |
| { |
| my $string = $g_ExeRegion{$i}->[0]; |
| next if ($string ne $strExeRegionName); |
| } |
| |
| if ($nOption == Region::Size) |
| { |
| $strInfo = "0x".$g_ExeRegion{$index}->[Region::Size]; |
| } |
| elsif ($nOption == Region::VMA) |
| { |
| $strInfo = "0x".$g_ExeRegion{$index}->[Region::VMA]; |
| } |
| elsif ($nOption == Region::LMA) |
| { |
| $strInfo = "0x".$g_ExeRegion{$index}->[Region::LMA]; |
| } |
| elsif ($nOption == Region::Offsets) |
| { |
| $strInfo = "0x".$g_ExeRegion{$index}->[Region::Offsets]; |
| } |
| elsif ($nOption == Region::Align) |
| { |
| $strInfo = $g_ExeRegion{$index}->[Region::Align]; |
| } |
| elsif ($nOption == Region::Attr) |
| { |
| $strInfo = $Attr{$strExeRegionName}; |
| } |
| |
| return $strInfo; |
| } |
| |
| #**************************************************************************** |
| # subroutine: FootprintAnalyzeBySymbol |
| # input: $strSymName: Symbol Name (Case sensitive) |
| # output: symbol info array reference |
| #**************************************************************************** |
| sub FootprintAnalyzeBySymbol |
| { |
| return undef; |
| } |