rjw | 6c1fd8f | 2022-11-30 14:33:01 +0800 | [diff] [blame] | 1 | #!/usr/bin/perl |
| 2 | # |
| 3 | # Copyright Statement: |
| 4 | # -------------------- |
| 5 | # This software is protected by Copyright and the information contained |
| 6 | # herein is confidential. The software may not be copied and the information |
| 7 | # contained herein may not be used or disclosed except with the written |
| 8 | # permission of MediaTek Inc. (C) 2006 |
| 9 | # |
| 10 | # BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES |
| 11 | # THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") |
| 12 | # RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON |
| 13 | # AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, |
| 14 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF |
| 15 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. |
| 16 | # NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE |
| 17 | # SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR |
| 18 | # SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH |
| 19 | # THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO |
| 20 | # NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S |
| 21 | # SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. |
| 22 | # |
| 23 | # BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE |
| 24 | # LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, |
| 25 | # AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, |
| 26 | # OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO |
| 27 | # MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. |
| 28 | # |
| 29 | # THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE |
| 30 | # WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF |
| 31 | # LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND |
| 32 | # RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER |
| 33 | # THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). |
| 34 | # |
| 35 | #***************************************************************************** |
| 36 | #* |
| 37 | #* Filename: |
| 38 | #* --------- |
| 39 | #* FileInfoParser.pm |
| 40 | #* |
| 41 | #* Project: |
| 42 | #* -------- |
| 43 | #* |
| 44 | #* |
| 45 | #* Description: |
| 46 | #* ------------ |
| 47 | #* This module collects the subroutines for common utility. |
| 48 | #* |
| 49 | #* |
| 50 | #* Author: |
| 51 | #* ------- |
| 52 | #* Carl Kao (mtk08237) |
| 53 | #* |
| 54 | #****************************************************************************/ |
| 55 | |
| 56 | use strict; |
| 57 | BEGIN{push(@INC,'../', './tools/', './tools/MemoryUtility/')}; |
| 58 | use CommonUtility; |
| 59 | use Digest::MD5; |
| 60 | |
| 61 | package Region; |
| 62 | use constant Size => 1; |
| 63 | use constant VMA => 2; |
| 64 | use constant LMA => 3; |
| 65 | use constant Offsets => 4; |
| 66 | use constant Align => 5; |
| 67 | use constant Attr => 6; |
| 68 | |
| 69 | # for %g_SymTable = (); |
| 70 | package SymTable; |
| 71 | use constant Name => 0; |
| 72 | use constant Addr => 1; |
| 73 | use constant Group => 2; |
| 74 | use constant Region => 3; |
| 75 | use constant Size => 4; |
| 76 | use constant Obj => 5; |
| 77 | use constant NeedMerge => 6; |
| 78 | |
| 79 | # for %symbol = (); |
| 80 | package Symbol; |
| 81 | use constant Addr => 0; |
| 82 | use constant Region => 3; |
| 83 | use constant Size => 4; |
| 84 | |
| 85 | # for %g_LinkerSymbol = (); |
| 86 | package LinkerSymbol; |
| 87 | use constant Addr => 0; |
| 88 | use constant Group => 1; |
| 89 | use constant Region => 2; |
| 90 | use constant Size => 3; |
| 91 | |
| 92 | package LinkerSymPostfix; |
| 93 | use constant Base => 0; |
| 94 | use constant Limit => 1; |
| 95 | use constant ZIBase => 2; |
| 96 | use constant ZILimit => 3; |
| 97 | use constant Length => 4; |
| 98 | use constant ZILength => 5; |
| 99 | |
| 100 | package LinkerSymPrefix; |
| 101 | use constant Image => 0; |
| 102 | use constant Load => 1; |
| 103 | use constant None => 2; |
| 104 | |
| 105 | #**************************************************************************** |
| 106 | # Constants |
| 107 | #**************************************************************************** |
| 108 | my $SYM_FILE_PARSER_VERNO = " u0.07"; |
| 109 | # u0.07 , 2015/10/28, Carl, Support LinkerSymPostfix::ZILength |
| 110 | # u0.06 , 2015/01/22, Carl, Add parsing rule for GCC 4.9.3 |
| 111 | # u0.05 , 2015/01/19, Carl, Memory Utility Refinement |
| 112 | # u0.04, 2014/09/26, Carl, Add constant for LinkerSymPrefix |
| 113 | # u0.03, 2014/09/16, Carl, Add parsing rule for GCC 4.9.2 |
| 114 | # u0.02, 2014/03/03, BM, Refine inculde path |
| 115 | # u0.01, 2014/02/20, BM, Init version, branch from MOLY |
| 116 | |
| 117 | #**************************************************************************** |
| 118 | # Global variable |
| 119 | #**************************************************************************** |
| 120 | package SymFileParser; |
| 121 | |
| 122 | my $g_SYMPath; |
| 123 | my %symbol; |
| 124 | my $DUMMY_END_size; |
| 125 | my $DUMMY_END_base; |
| 126 | my %g_SymTable; # $strAddress.$strSymbolName => [strSymbol, $strAddress, strGroup, strRegion, nSize] |
| 127 | my %g_LinkerSymbol; # $strSymbolName => [$strAddress, strGroup, strRegion, nSize] |
| 128 | my %g_static_symbol_loookup; #$strSymbolName.".".$strObjName = [$strAddress, strGroup, strRegion, nSize] |
| 129 | |
| 130 | my $g_PreviousParsedSYMChecksum; |
| 131 | my $g_PreviousParsedSYMPath; |
| 132 | |
| 133 | my %g_ExeRegion;# Execution Region |
| 134 | my %g_ExeRegionLookUpTable; # RegionName -> Index |
| 135 | my %Attr; |
| 136 | |
| 137 | #**************************************************************************** |
| 138 | # oo >>> Finished |
| 139 | #**************************************************************************** |
| 140 | return 1; |
| 141 | |
| 142 | #**************************************************************************** |
| 143 | # subroutine: SYM_die |
| 144 | # sample code: (message, __FILE__, __LINE__) |
| 145 | # input: $error_msg, $file, $line_no |
| 146 | #**************************************************************************** |
| 147 | sub SYM_die |
| 148 | { |
| 149 | my ($error_msg, $file, $line_no) = (@_); |
| 150 | &CommonUtil::error_handler($error_msg, $file, $line_no, 'SYM'); |
| 151 | } |
| 152 | |
| 153 | #**************************************************************************** |
| 154 | # subroutine: ParseSYM |
| 155 | # input: SYM Path string |
| 156 | # output: x |
| 157 | #**************************************************************************** |
| 158 | sub Clean |
| 159 | { |
| 160 | %symbol = (); |
| 161 | %g_ExeRegion = (); |
| 162 | %g_ExeRegionLookUpTable = (); |
| 163 | %g_SymTable = (); |
| 164 | %g_LinkerSymbol = (); |
| 165 | %Attr = (); |
| 166 | $DUMMY_END_size = 0; |
| 167 | $DUMMY_END_size = 0; |
| 168 | } |
| 169 | |
| 170 | sub ParseSYM |
| 171 | { |
| 172 | ($g_SYMPath) = (@_); |
| 173 | if(defined $g_SYMPath and -e $g_SYMPath) |
| 174 | { |
| 175 | open (my $fh, '<', $g_SYMPath) or &SYM_die("$g_SYMPath: file error!", __FILE__, __LINE__); |
| 176 | binmode ($fh); |
| 177 | my $SYMChecksum = Digest::MD5->new->addfile($fh)->hexdigest; |
| 178 | |
| 179 | if($g_SYMPath eq $g_PreviousParsedSYMPath and $SYMChecksum eq $g_PreviousParsedSYMChecksum) |
| 180 | { |
| 181 | #print "Sym File: $g_SYMPath was parsed before and not modified, skip PasrseSYM\n"; |
| 182 | close($fh); |
| 183 | return; |
| 184 | } |
| 185 | close($fh); |
| 186 | |
| 187 | Clean(); |
| 188 | open (FILE_HANDLE, "<$g_SYMPath") or &SYM_die("$g_SYMPath: file error!", __FILE__, __LINE__); |
| 189 | my $strPreExeRegionName = undef; |
| 190 | my $bBegin = 0; #0= Program Header: begin, 1= Sections begin, 2=SYMBOL TABLE: begin |
| 191 | my $strObjName = undef; #parse static symbol's obj |
| 192 | |
| 193 | while (<FILE_HANDLE>) |
| 194 | { |
| 195 | my $strLine = $_; |
| 196 | $bBegin = 1 if($strLine =~/^Sections:$/);#begin parse section table |
| 197 | $bBegin = 2 if($strLine =~/^SYMBOL TABLE:$/);#begin parse symbol table |
| 198 | |
| 199 | if ($strLine =~ /\.hidden\s/) |
| 200 | { |
| 201 | $strObjName = undef;#no static symbol after '.hidden' |
| 202 | |
| 203 | # add this rule for GCC 4.9.3 |
| 204 | # [4.9.2] a0401ee4 g O CACHED_EXTSRAM 00000008 .hidden __CTOR_LIST__ |
| 205 | $strLine =~ s|\.hidden\s||g; |
| 206 | } |
| 207 | |
| 208 | last if($strLine =~/^RELOCATION RECORDS FOR \[ROM\]:$/); |
| 209 | |
| 210 | ## begin to parse section table |
| 211 | if ($bBegin == 1 and |
| 212 | $strLine =~ /\s*(\d+)\s+(\S+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\S+)/) |
| 213 | { # Idx Name Size VMA LMA File off Algn |
| 214 | # 0 BL_GFH_SECTION 00000170 7000a000 7000a000 00002000 2**2 |
| 215 | $g_ExeRegion{$1}= [$2, $3, $4, $5, $6, $7]; |
| 216 | $g_ExeRegionLookUpTable{$2} = $1; |
| 217 | $strPreExeRegionName = $2; |
| 218 | next; |
| 219 | } |
| 220 | elsif($bBegin == 1 and defined $strPreExeRegionName) |
| 221 | { #parse section attribution |
| 222 | &ParseInputSection($strPreExeRegionName, $strLine); |
| 223 | next; |
| 224 | } |
| 225 | |
| 226 | ## begin to parse symbol table |
| 227 | $strObjName = ParseSymbolTable($strLine,$strObjName) if($bBegin == 2); |
| 228 | |
| 229 | if ($bBegin ==2 and $strLine =~ /DUMMY_END\$\$Base/) |
| 230 | { # f3fc0000 g *ABS* 00000000 Image$$CACHED_DUMMY_END$$Base |
| 231 | |
| 232 | if(/^(\w+)\s+(\w+)\s+(.*)\s+(\w+)/) |
| 233 | { |
| 234 | $DUMMY_END_size = hex($4); |
| 235 | $DUMMY_END_base = "0x".$1; |
| 236 | } |
| 237 | next; |
| 238 | } |
| 239 | elsif ($bBegin ==2 and |
| 240 | $strLine =~ /^(\w+)\s+(\w+)\s+(\w+)\s+(\S+)\s+(\w+)\s+(\w+)$/) |
| 241 | { # 7000a000 l d BL_GFH_SECTION 00000000 BL_GFH_SECTION |
| 242 | next if (($2 ne "g") && ($2 ne "l") && ($2 ne "w")); |
| 243 | next if (($3 ne "F") && ($3 ne "O")); |
| 244 | my $symbol_name = $6; |
| 245 | my $base_address = $1; |
| 246 | my $execution_region = $4; |
| 247 | my $size = $5; |
| 248 | $symbol{$symbol_name} = [$1, $2, $3, $4, $5]; |
| 249 | next; |
| 250 | } |
| 251 | elsif ($bBegin ==2 and |
| 252 | $strLine =~ /^(\w+)\s+(\w+)\s+(\w+)\s+(\S+)\s+(\w+)\s+(\w+)\s+(\w+)$/) |
| 253 | { # 901c2ae8 g F ROM 00000048 0xf0 EL1D_LPWR_Other_Core_Has_Run_Determine |
| 254 | next if (($2 ne "g") && ($2 ne "l") && ($2 ne "w")); |
| 255 | next if (($3 ne "F") && ($3 ne "O")); |
| 256 | my $symbol_name = $7; |
| 257 | my $base_address = $1; |
| 258 | my $execution_region = $4; |
| 259 | my $size = $5; |
| 260 | $symbol{$symbol_name} = [$1, $2, $3, $4, $5]; |
| 261 | next; |
| 262 | } |
| 263 | |
| 264 | } |
| 265 | close FILE_HANDLE; |
| 266 | &FixInputSectionLMAValue(); |
| 267 | |
| 268 | #record parsed sym file path and file checksum |
| 269 | $g_PreviousParsedSYMPath = $g_SYMPath; |
| 270 | $g_PreviousParsedSYMChecksum = $SYMChecksum; |
| 271 | } |
| 272 | else |
| 273 | { |
| 274 | &SYM_die("SYM Path($g_SYMPath) doesn't exist", __FILE__, __LINE__); |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | sub ParseSymbolTable |
| 279 | { |
| 280 | my ($strLine,$strObjName) = @_; |
| 281 | my $bSearched = 0; |
| 282 | my ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize); |
| 283 | |
| 284 | if($strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+.+\\(\S+)\./ |
| 285 | ||$strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+.+\/(\S+)\./) |
| 286 | { #parse file name |
| 287 | #00000000 l df *ABS* 00000000 protocol/as_multimode/dbme/src/db_io.c |
| 288 | $strObjName = $2.".obj"; |
| 289 | } |
| 290 | elsif($strLine =~ /^(\w+)\s+l\s+df\s+\*ABS\*\s+\w+\s+(\S+)\./) |
| 291 | { #parse file name |
| 292 | #00000000 l df *ABS* 00000000 db_io.c |
| 293 | $strObjName = $2.".obj"; |
| 294 | } |
| 295 | elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\S+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/) |
| 296 | {#90338508 g F ROM 0000002e 0xf0 FT_GetDiskFreeSpace |
| 297 | ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($7, "0x".$1, $2.$3, $4, hex($5)); |
| 298 | $bSearched = 1; |
| 299 | } |
| 300 | elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/) |
| 301 | {#0001622c l F ROM 000001b4 ast_hif_mcu_lisr_handler |
| 302 | ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($6, "0x".$1, $2.$3, $4, hex($5)); |
| 303 | $bSearched = 1; |
| 304 | } |
| 305 | elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\w+|\w+\.\d+)(\.\D\S+\.\d+)?$/) |
| 306 | {#90004200 l ROM 00000000 IRQ0_VEC |
| 307 | ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($5, "0x".$1, $2, $3, hex($4)); |
| 308 | $bSearched = 1; |
| 309 | } |
| 310 | elsif($strLine =~ /^(\w+)\s+(\S+)\s+(\S+)\s+(\w+)\s+(\S+\$\$\S+)$/) |
| 311 | {#f06185f1 g CACHED_EXTSRAM 00000000 BUILD_TIME_RW$$Base |
| 312 | ($strSymbolName, $strAddress, $strGroup, $strRegion, $nSize) = ($5, "0x".$1, $2, $3, hex($4)); |
| 313 | $bSearched = 1; |
| 314 | } |
| 315 | |
| 316 | if($bSearched) |
| 317 | { |
| 318 | if($strGroup ne "l" and $strGroup ne "ldf" and $strGroup ne "ld") |
| 319 | {#skip 00000000 l *ABS* 00000000 MT6589 |
| 320 | #skip 00000000 l df *ABS* 00000000 ft_fnc_fat.c |
| 321 | |
| 322 | ## parse linker symbol |
| 323 | if($strSymbolName =~ /\$\$/ and (($strGroup eq "g") or ($strGroup eq "w"))) |
| 324 | { |
| 325 | $g_LinkerSymbol{$strSymbolName} = [$strAddress, $strGroup, $strRegion, $nSize]; |
| 326 | } |
| 327 | |
| 328 | ##parse static symbol |
| 329 | elsif($strObjName and (($strGroup eq "lO") or ($strGroup eq "lF"))) |
| 330 | { |
| 331 | #****************************************** |
| 332 | # Static symbol need to be merged |
| 333 | # |
| 334 | # Before merge: |
| 335 | # 900bcdf0 l F ROM 00000230 ssleay_rand_add.part.0 |
| 336 | # 900bd020 l F ROM 00000008 ssleay_rand_add |
| 337 | # |
| 338 | # After merge: |
| 339 | # 900bcdf0 l F ROM 00000238 ssleay_rand_add |
| 340 | #****************************************** |
| 341 | |
| 342 | my $need_merge = ($strLine=~/\.part\./)?1:0; |
| 343 | |
| 344 | if($g_static_symbol_loookup{$strSymbolName.".".$strObjName} && ($need_merge || $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::NeedMerge])) |
| 345 | { |
| 346 | if($g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Addr] <= $strAddress) |
| 347 | { |
| 348 | $strAddress = $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Addr]; |
| 349 | } |
| 350 | else |
| 351 | { |
| 352 | delete $g_SymTable{$strAddress.".".$strSymbolName}; |
| 353 | } |
| 354 | |
| 355 | $nSize += $g_static_symbol_loookup{$strSymbolName.".".$strObjName}->[SymTable::Size]; |
| 356 | $g_static_symbol_loookup{$strSymbolName.".".$strObjName} = [$strSymbolName,$strAddress, $strGroup, $strRegion, $nSize, $strObjName, $need_merge]; |
| 357 | $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName]; |
| 358 | } |
| 359 | else |
| 360 | { |
| 361 | $g_static_symbol_loookup{$strSymbolName.".".$strObjName} = [$strSymbolName,$strAddress, $strGroup, $strRegion, $nSize, $strObjName, $need_merge]; |
| 362 | $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize,$strObjName]; |
| 363 | } |
| 364 | } |
| 365 | ## parse global symbol |
| 366 | else |
| 367 | { |
| 368 | print "$strAddress.$strSymbolName appears before\n" if(exists $g_SymTable{$strAddress.".".$strSymbolName}); |
| 369 | $g_SymTable{$strAddress.".".$strSymbolName} = [$strSymbolName, $strAddress, $strGroup, $strRegion, $nSize]; |
| 370 | } |
| 371 | } |
| 372 | elsif($strGroup eq "l" && $strSymbolName =~ /\$\$/) |
| 373 | {# add this rule for GCC 4.9.2 |
| 374 | # 01400000 l L1CORE_RWZI 00000000 Image$$L1CORE_RWZI$$ZI$$Base |
| 375 | $g_LinkerSymbol{$strSymbolName} = [$strAddress, $strGroup, $strRegion, $nSize]; |
| 376 | } |
| 377 | } |
| 378 | return $strObjName; |
| 379 | } |
| 380 | |
| 381 | #**************************************************************************** |
| 382 | # subroutine: GetSymbolTable |
| 383 | # input: N/A |
| 384 | # output: get all symbol table in .sym file |
| 385 | # |
| 386 | #**************************************************************************** |
| 387 | sub GetSymbolTable |
| 388 | { |
| 389 | my @symbol = values %g_SymTable; |
| 390 | return \@symbol; |
| 391 | } |
| 392 | |
| 393 | #**************************************************************************** |
| 394 | # subroutine: GetSymbol |
| 395 | # input: N/A |
| 396 | # output: get all symbol info in .sym file |
| 397 | # NOTE: The info for global symbol is right; |
| 398 | # but for static symbol which has same name with other symbol, the info maybe wrong. |
| 399 | #**************************************************************************** |
| 400 | sub GetSymbol |
| 401 | { |
| 402 | return \%symbol; |
| 403 | } |
| 404 | |
| 405 | sub GetLinkerSymbol |
| 406 | { |
| 407 | return \%g_LinkerSymbol; |
| 408 | } |
| 409 | |
| 410 | sub GrepSymbolBySection |
| 411 | { |
| 412 | my ($strSection) = @_; |
| 413 | my @SymKeys = sort { hex($g_SymTable{$a}->[SymTable::Addr]) <=> hex($g_SymTable{$b}->[SymTable::Addr]) } |
| 414 | grep{$g_SymTable{$_}->[SymTable::Region] eq $strSection} keys %g_SymTable; |
| 415 | #map {print $_."\n"} @SymKeys; |
| 416 | my @SymInfo = map {$g_SymTable{$_}} @SymKeys; |
| 417 | return \@SymInfo; |
| 418 | } |
| 419 | |
| 420 | sub GrepSymbolByOutputSection |
| 421 | { |
| 422 | my ($strSection) = @_; |
| 423 | my $strStart = GetLinkerSymbolAddress($strSection, LinkerSymPostfix::Base, LinkerSymPrefix::Image); |
| 424 | my $strEnd = GetLinkerSymbolAddress($strSection, LinkerSymPostfix::ZILimit, LinkerSymPrefix::Image); |
| 425 | my @SymInfo; |
| 426 | |
| 427 | if((hex($strEnd) - hex($strStart)) > 0) |
| 428 | { |
| 429 | my @SymKeys = sort { hex($g_SymTable{$a}->[SymTable::Addr]) <=> hex($g_SymTable{$b}->[SymTable::Addr]) } |
| 430 | grep{(hex($g_SymTable{$_}->[SymTable::Addr]) >= hex($strStart)) and |
| 431 | (hex($g_SymTable{$_}->[SymTable::Addr]) < hex($strEnd ))} keys %g_SymTable; |
| 432 | @SymInfo = map {$g_SymTable{$_}} @SymKeys; |
| 433 | } |
| 434 | return \@SymInfo; |
| 435 | } |
| 436 | |
| 437 | #**************************************************************************** |
| 438 | # subroutine: GetLinkerSymbolAddress |
| 439 | # input: $strRegionName, $nLocation, $nRegionType |
| 440 | # output: $strAddr |
| 441 | # NOTE: |
| 442 | # nRegionType = 0: Execution Region |
| 443 | # nRegionType = 1: Load Region |
| 444 | # nRegionType = 2: Input Section |
| 445 | #**************************************************************************** |
| 446 | sub GetLinkerSymbolAddress |
| 447 | { |
| 448 | my ($strRegionName, $nLocation, $nRegionType) = @_; |
| 449 | my $strPrefix = 'Image$$'; |
| 450 | if($nRegionType == 1) |
| 451 | { |
| 452 | $strPrefix = 'Load$$' ; |
| 453 | $nLocation = 0; |
| 454 | } |
| 455 | elsif($nRegionType == 2) |
| 456 | { |
| 457 | $strPrefix = ""; |
| 458 | } |
| 459 | my $strPostfix = '$$Base'; #LinkerSymPostfix::Base |
| 460 | $strPostfix = '$$Limit' if($nLocation == LinkerSymPostfix::Limit); |
| 461 | $strPostfix = '$$ZI$$Base' if($nLocation == LinkerSymPostfix::ZIBase); |
| 462 | $strPostfix = '$$ZI$$Limit' if($nLocation == LinkerSymPostfix::ZILimit); |
| 463 | $strPostfix = '$$Length' if($nLocation == LinkerSymPostfix::Length); |
| 464 | $strPostfix = '$$ZI$$Length'if($nLocation == LinkerSymPostfix::ZILength); |
| 465 | my $strSymbolName = $strPrefix.uc($strRegionName).$strPostfix; |
| 466 | my $strAddr = undef; |
| 467 | $strAddr = $g_LinkerSymbol{$strSymbolName}->[0] if(exists $g_LinkerSymbol{$strSymbolName}); |
| 468 | return $strAddr; |
| 469 | } |
| 470 | |
| 471 | #**************************************************************************** |
| 472 | # subroutine: Get_DUMMY_END_Size |
| 473 | # input: N/A |
| 474 | # output: size of DUMMY_END region |
| 475 | #**************************************************************************** |
| 476 | sub Get_DUMMY_END_Size |
| 477 | { |
| 478 | return $DUMMY_END_size; |
| 479 | } |
| 480 | |
| 481 | #**************************************************************************** |
| 482 | # subroutine: Get_DUMMY_END_Base |
| 483 | # input: N/A |
| 484 | # output: base address of DUMMY_END region |
| 485 | #**************************************************************************** |
| 486 | sub Get_DUMMY_END_Base |
| 487 | { |
| 488 | return $DUMMY_END_base; |
| 489 | } |
| 490 | |
| 491 | #**************************************************************************** |
| 492 | # subroutine: StoreIntoTempFile |
| 493 | # input: N/A |
| 494 | # output: temp files which contain perl data structure |
| 495 | #**************************************************************************** |
| 496 | use Storable qw/lock_nstore/; |
| 497 | sub StoreIntoTempFile |
| 498 | { |
| 499 | my ($strPath) = @_; |
| 500 | my $file = $strPath."\\SymParser_Temp.dat"; |
| 501 | my %tempfile; |
| 502 | |
| 503 | $tempfile{"execution_region"} = \%g_ExeRegion; |
| 504 | $tempfile{"symbol_info"} = \%symbol; |
| 505 | |
| 506 | lock_nstore \%tempfile, $file; |
| 507 | } |
| 508 | |
| 509 | #**************************************************************************** |
| 510 | # subroutine: ParseInputSection. used by ParseSYM to parse Execution Region Attribute |
| 511 | # input: 1. Execution Name, 2. $strLine |
| 512 | # output: x |
| 513 | #**************************************************************************** |
| 514 | sub ParseInputSection |
| 515 | { |
| 516 | my ($strExeRegionName, $strLine) = @_; |
| 517 | return if(!defined $strExeRegionName);#setting for $strExeRegionName = undef |
| 518 | |
| 519 | my $attr = undef; |
| 520 | chomp($strLine); |
| 521 | if($strLine =~ /\s+(.*)/) |
| 522 | { |
| 523 | #CONTENTS, ALLOC, LOAD, READONLY, DATA |
| 524 | $Attr{$strExeRegionName} = $1; |
| 525 | } |
| 526 | } |
| 527 | |
| 528 | #**************************************************************************** |
| 529 | # subroutine: FixInputSectionLMAValue is used to fix the wrong LMA value |
| 530 | # record in InputSection |
| 531 | # input: x |
| 532 | # output: x |
| 533 | #**************************************************************************** |
| 534 | sub FixInputSectionLMAValue |
| 535 | { |
| 536 | while(my($strSymbolName, $arySymbolDataRef) = each %g_LinkerSymbol) |
| 537 | { |
| 538 | my @arySymbolData = @$arySymbolDataRef;# arySymbolData: 0x00760eb0 g *ABS* 0 |
| 539 | #print "arySymbolData: @arySymbolData \n"; |
| 540 | if($strSymbolName =~ /Load\$\$(\S+)\$\$Base/)# $strSymbolName = Load$$EXTSRAM_DSP_RX$$Base |
| 541 | {# Load$$EXTSRAM_DSP_RX$$Base |
| 542 | my $strExeRegionName = $1;# $strExeRegionName = EXTSRAM_DSP_RX |
| 543 | |
| 544 | #check if $strExeRegionName exist in $g_ExeRegionLookUpTable |
| 545 | if(exists $g_ExeRegionLookUpTable{$strExeRegionName}) |
| 546 | { |
| 547 | #extract the correct LMA value record in SymbolTable |
| 548 | my $strCorrectLMAValue = $arySymbolData[LinkerSymbol::Addr]; |
| 549 | $strCorrectLMAValue =~ s/0x//; |
| 550 | #print "strCorrectLMAValue: $strCorrectLMAValue \n"; |
| 551 | |
| 552 | #fix LMA value stored in %g_ExeRegion |
| 553 | my $lookupIndex = $g_ExeRegionLookUpTable{$strExeRegionName}; |
| 554 | #print "look up index: ".$lookupIndex."\n"; |
| 555 | $g_ExeRegion{$lookupIndex}[Region::LMA] = $strCorrectLMAValue; |
| 556 | } |
| 557 | } |
| 558 | } |
| 559 | } |
| 560 | |
| 561 | #**************************************************************************** |
| 562 | # subroutine: ListAllExeRegion |
| 563 | # input: $bTrimDebugRegion: 1= NeedtoTrimDebugRegion, 0 or undef=NoNeedToTrimDebugRegion |
| 564 | # output: Execution Region List |
| 565 | #**************************************************************************** |
| 566 | sub ListAllExeRegion |
| 567 | { |
| 568 | my ($bTrimDebugRegion) = @_; |
| 569 | my @k = keys %g_ExeRegion; |
| 570 | my @ExeRegion; |
| 571 | my $ExeRegion_aref = undef; |
| 572 | for (my $i = 0; $i <= $#k; $i++) |
| 573 | { |
| 574 | push(@ExeRegion,$g_ExeRegion{$i}->[0]); |
| 575 | } |
| 576 | $ExeRegion_aref = \@ExeRegion; |
| 577 | if($bTrimDebugRegion) |
| 578 | { |
| 579 | $ExeRegion_aref = TrimDebugRegion(\@ExeRegion); |
| 580 | } |
| 581 | return $ExeRegion_aref; |
| 582 | } |
| 583 | #**************************************************************************** |
| 584 | # subroutine: TrimDebugRegion |
| 585 | # input: All Regions in array reference |
| 586 | # output: Execution Region List(array reference) after trimming |
| 587 | #**************************************************************************** |
| 588 | sub TrimDebugRegion |
| 589 | { |
| 590 | my ($ERs_aref) = @_; |
| 591 | my @RealERs; |
| 592 | foreach my $region (@$ERs_aref) |
| 593 | { |
| 594 | if ( $region !~ /^\.debug_/ |
| 595 | and $region !~ /^\.ARM\.attributes/ |
| 596 | and $region !~ /^\.comment/ |
| 597 | and $region !~ /^\.stab/ |
| 598 | and $region ne "") |
| 599 | { |
| 600 | push(@RealERs , $region); |
| 601 | } |
| 602 | } |
| 603 | return \@RealERs; |
| 604 | } |
| 605 | |
| 606 | #**************************************************************************** |
| 607 | # subroutine: GetExeRegionInfo |
| 608 | # input: Execution Region Name, $nOption |
| 609 | # $nOption = Region::VMA or Region::LMA or Region::Size |
| 610 | # or Region::Offsets or Region::Align or Region::Attr |
| 611 | # output: string of corresponding Execution Region Infomation |
| 612 | #**************************************************************************** |
| 613 | sub GetExeRegionInfo |
| 614 | { |
| 615 | # Name Size VMA LMA File off Algn |
| 616 | my ($strExeRegionName, $nOption) = @_; |
| 617 | my $index = $g_ExeRegionLookUpTable{$strExeRegionName}; |
| 618 | my @ExeRegionInfo; |
| 619 | my $strInfo; |
| 620 | my @k = keys %g_ExeRegion; |
| 621 | my $key_count = $#k + 1; |
| 622 | for (my $i = 0; $i <= $#k; $i++) |
| 623 | { |
| 624 | my $string = $g_ExeRegion{$i}->[0]; |
| 625 | next if ($string ne $strExeRegionName); |
| 626 | } |
| 627 | |
| 628 | if ($nOption == Region::Size) |
| 629 | { |
| 630 | $strInfo = "0x".$g_ExeRegion{$index}->[Region::Size]; |
| 631 | } |
| 632 | elsif ($nOption == Region::VMA) |
| 633 | { |
| 634 | $strInfo = "0x".$g_ExeRegion{$index}->[Region::VMA]; |
| 635 | } |
| 636 | elsif ($nOption == Region::LMA) |
| 637 | { |
| 638 | $strInfo = "0x".$g_ExeRegion{$index}->[Region::LMA]; |
| 639 | } |
| 640 | elsif ($nOption == Region::Offsets) |
| 641 | { |
| 642 | $strInfo = "0x".$g_ExeRegion{$index}->[Region::Offsets]; |
| 643 | } |
| 644 | elsif ($nOption == Region::Align) |
| 645 | { |
| 646 | $strInfo = $g_ExeRegion{$index}->[Region::Align]; |
| 647 | } |
| 648 | elsif ($nOption == Region::Attr) |
| 649 | { |
| 650 | $strInfo = $Attr{$strExeRegionName}; |
| 651 | } |
| 652 | |
| 653 | return $strInfo; |
| 654 | } |
| 655 | |
| 656 | #**************************************************************************** |
| 657 | # subroutine: FootprintAnalyzeBySymbol |
| 658 | # input: $strSymName: Symbol Name (Case sensitive) |
| 659 | # output: symbol info array reference |
| 660 | #**************************************************************************** |
| 661 | sub FootprintAnalyzeBySymbol |
| 662 | { |
| 663 | return undef; |
| 664 | } |