blob: 72ae72c0e69e9ca876a63f5406aedb508fed071a [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001#!/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#* DetectZI.pl
40#*
41#* Project:
42#* --------
43#*
44#*
45#* Description:
46#* ------------
47#* This perl is used to detect ZI which be declared as RW
48#*
49#*
50#* Author:
51#* -------
52#* Cark Kao (mtk08237)
53#*
54#****************************************************************************/
55
56BEGIN { push @INC, '../', './tools/', './tools/MemoryUtility/' }
57
58use strict;
59use File::Basename;
60use LinkerOutputParser;
61use CommonUtility;
62
63use constant EXEC_VIEW => 0;
64use constant LOAD_VIEW => 1;
65
66
67my $nVerion = "v1.10";
68 # v1.10 , 20160303 , Tero , Search RW sections from symbol file. Removed var and obj info hash table init.
69 # v1.09 , 20151105 , Carl , Change DSP TX/RX sections to ZI (.bss) section
70 # v1.08 , 20151030 , Carl , Parsing ELF file instead of parsing BIN file since there is CCCI header in front of bin file
71 # v1.07 , 20150918 , Carl , Modify for LR11
72 # v1.06 , 20150121 , Carl , Calaulate ROM base for L1core
73 # v1.05 , 20150121 , Carl , Add shared region to serach sections
74 # v1.04 , 20150119 , Carl , Memory Utility Refinement
75 # v1.03 , 20141022 , Carl , Remove DSP section since they are ZI now
76 # v1.02 , 20140910 , Carl , Add symbol filter
77 # v1.01 , 20140909 , Carl , Reduce parsing time of map, sym file for speedup
78 # v1.00 , 20140827 , Carl , Init version
79
80
81
82#################################################################
83############# Configurable variable are list below ############
84#################################################################
85
86# serach sections
87my @aSection;
88# filter-out symbol file
89my($filename, $dirs, $suffix) = fileparse($0);
90my $strSymbolFilterFilePath = $dirs."config/detectZI_filter.txt";
91
92#################################################################
93#################################################################
94#################################################################
95
96
97
98# 1. input sym, map, bin file
99
100&Usage() if ($#ARGV < 2);
101
102my ($sym_file, $map_file, $elf_file, $gnZIpercent, $gnZIthreshold) = @ARGV;
103
104$gnZIpercent = 100 if( $gnZIpercent eq "" );
105$gnZIthreshold = 0 if( $gnZIthreshold eq "" );
106
107$sym_file =~ s/\\/\\\\/;
108$map_file =~ s/\\/\\\\/;
109$elf_file =~ s/\\/\\\\/;
110
111print "project info: $map_file\n\n";
112
113
114# 2. main(). lisr all RW sections
115
116my $nTotalZI;
117my %var_info; # var_name => [ var size, obj name, section name ]
118my %obj_info; # obj_name => [ total ZI var size, var_1, var_2, ... ]
119my %filter_out_symbol;
120my $gnROMBase;
121
122#&GenROMBase();
123
124&take_filter_out_symbol();
125
126&process_with_value(100,0) if ( 100==$gnZIpercent );
127&process_with_value($gnZIpercent, $gnZIthreshold) if ( 100!=$gnZIpercent );
128
129
130sub take_filter_out_symbol()
131{
132 my $strContent = CommonUtil::GetFileContent($strSymbolFilterFilePath);
133 my @symbol = split(/\s/, $strContent);
134
135 # note that we also take the "commont" as filter out symbol
136 foreach (@symbol)
137 {
138 $filter_out_symbol{$_} = 1;
139 }
140}
141
142sub init_Glob()
143{
144 $nTotalZI=0;
145}
146
147sub process_with_value
148{
149 &init_Glob();
150
151 my ($nZIpercent, $nZIthreshold) = @_;
152
153 print "==============================================================\n";
154 print "=====nZIpercent: $nZIpercent, nZIthreshold: $nZIthreshold=====\n";
155 print "==============================================================\n";
156
157
158 my %sectionInfo;
159 LinkerOutputParser::FileParse($sym_file);
160 my $allSections = &LinkerOutputParser::ListAllExeRegion(1);
161 print "\nData load sections:\n";
162 foreach my $Section (@$allSections)
163 {
164 my $secinfo = LinkerOutputParser::GetExeRegionInfo($Section,Region::Attr);
165 if (($secinfo =~ /LOAD/) and ($secinfo =~ /DATA/))
166 {
167 print "$Section\n";
168 push @aSection, $Section;
169 }
170 }
171 print "\n";
172 if( 100 == $nZIpercent ) {
173 print("Section\tObj_file\tSymbol\tSize\n");
174 } else {
175 print("Section\tObj_file\tSymbol\tSymbol_size\tZI_Size\tRW_Size\tZI_percent\n");
176 }
177
178 foreach my $strSection (@aSection)
179 {
180 # (1) get base of load/execution address of section
181 my $nSectionElfOffset = hex(LinkerOutputParser::GetExeRegionInfo($strSection, Region::Offsets));
182 my $nSectionExecAddr = hex(LinkerOutputParser::GetExeRegionInfo($strSection, Region::VMA));
183
184 # (2) get all symbol in section
185 #[[SymbolName, address, size], ...] sorted by address
186 my $temp1_aref = LinkerOutputParser::GrepSymbolBySection("$strSection");
187
188 push @{$sectionInfo{$strSection}}, $nSectionElfOffset, $nSectionExecAddr, $temp1_aref;
189 }
190
191
192 LinkerOutputParser::FileParse($map_file);
193 foreach my $strSection (@aSection)
194 {
195 &detectZI($strSection, $nZIpercent, $nZIthreshold,
196 $sectionInfo{$strSection}[0],
197 $sectionInfo{$strSection}[1],
198 $sectionInfo{$strSection}[2]);
199 }
200 print "total ZI: $nTotalZI \n";
201
202 &print_result_by_var_size();
203 &print_result_by_obj_size();
204}
205
206
207# 3. start process section X
208
209sub detectZI
210{
211 my ($strSection, $nZIpercent, $nZIthreshold,
212 $nSectionElfOffset, $nSectionExecAddr, $temp1_aref) = @_;
213
214 # (3) open file
215
216 open (ELF_FILE_HANDLE, "<$elf_file") or &detectZI_die("[1.0] no elf file $elf_file");
217 binmode ELF_FILE_HANDLE;
218
219 # (4) for each symbol in section
220 foreach my $item (@$temp1_aref)
221 {
222 my $strVarName = @$item[SymTable::Name];
223 my $nVarAddr = hex(@$item[SymTable::Addr]);
224 my $nVarSize = @$item[SymTable::Size];
225 my $nVarAddrInElf = $nVarAddr - $nSectionExecAddr + $nSectionElfOffset;
226 # print "\t$strVarName, $nVarAddr, $nVarSize, $nVarAddrInElf, $nOffset \n";
227
228 next if (0 == $nVarSize || defined $filter_out_symbol{$strVarName} );
229
230 # <1> read content of symbol: {load address, load address+length}
231 # <2> if only zeros in the content, report it shoulbe be a ZI data
232
233 my ($bDetectZI, $nSeekLen, $nVarRWSize, $nVarZISize, $nVarZIpercent) = (1,0,0,0,0);
234
235 seek ELF_FILE_HANDLE, $nVarAddrInElf, 0;
236 for ( ; $nSeekLen < $nVarSize && (1==$bDetectZI||100!=$nZIpercent) ; ++$nSeekLen )
237 {
238 my ($nReadLen, $nData, $strData);
239 $nReadLen = read ELF_FILE_HANDLE, $nData, 1;
240 $strData = sprintf($nData);
241 if( "\c@" ne $strData )
242 {
243 $bDetectZI = 0;
244 $nVarRWSize++;
245 }
246 }
247
248 $nVarZISize = $nVarSize - $nVarRWSize;
249 $nVarZIpercent = $nVarZISize/$nVarSize*100;
250
251 if( $nZIpercent != 100 )
252 {
253 $bDetectZI = 1 if( 0 == $bDetectZI
254 && $nVarZIpercent >= $nZIpercent
255 && $nVarSize >= $nZIthreshold );
256
257 # no not show again
258 $bDetectZI = 0 if( 100==$nVarZIpercent);
259 }
260
261 if ( 1 eq $bDetectZI )
262 {
263 my $refObj = LinkerOutputParser::GetParentOfSymbol($strVarName, "obj");
264 my $strObjName = (defined $refObj?@$refObj[0]:"not_found");
265
266 # warning, we do not process the case: more than one symbol with same name
267 push @{$var_info{$strVarName}}, $nVarSize, $nVarZISize, $strObjName, $strSection;
268
269 if( !defined $obj_info{$strObjName } ){
270 push @{$obj_info{$strObjName}}, $nVarSize, $nVarZISize;
271 }else{
272 $obj_info{$strObjName}[0] += $nVarSize;
273 $obj_info{$strObjName}[1] += $nVarZISize;
274 }
275 push @{$obj_info{$strObjName}}, $strVarName;
276
277 print((defined $refObj?$strSection:"not_found_in_map_file"));
278 print("\t$strObjName\t$strVarName\t$nVarSize");
279 print(($nZIpercent != 100?"\t$nVarZISize\t$nVarRWSize\t$nVarZIpercent\n":"\n"));
280
281 $nTotalZI += $nVarSize;
282 }
283
284 }
285
286}
287
288
289sub print_result_by_var_size()
290{
291 return if (!%var_info); #No ZI variables
292 # sort by ZI size
293 my @list = sort { $var_info{$b}[1] <=> $var_info{$a}[1] } keys %var_info;
294
295 print "\n\n-->sort by symbol ZI size<--\n\n";
296
297 if( 100 == $gnZIpercent )
298 {
299 print("Symbol\tSize\tObj_file\tSection\n");
300 foreach my $strVarName (@list)
301 {
302 my $nVarSize = $var_info{$strVarName}[0];
303 my $strObjName = $var_info{$strVarName}[2];
304 my $strSection = $var_info{$strVarName}[3];
305
306 print "$strVarName\t$nVarSize\t$strObjName\t$strSection\n";
307 }
308 }
309 else
310 {
311 print("Symbol\tSymbol_size\tZI_Size\tRW_Size\tZI_percent\tObj_file\tSection\t\n");
312 foreach my $strVarName (@list)
313 {
314 my $nVarSize = $var_info{$strVarName}[0];
315 my $nVarZISize = $var_info{$strVarName}[1];
316 my $strObjName = $var_info{$strVarName}[2];
317 my $strSection = $var_info{$strVarName}[3];
318
319 next if( !defined $nVarSize );
320 my $nVarRWSize = $nVarSize - $nVarZISize;
321 my $nVarZIpercent = $nVarZISize/$nVarSize*100;
322
323 print "$strVarName\t$nVarSize\t$nVarZISize\t$nVarRWSize\t$nVarZIpercent\t$strObjName\t$strSection\n";
324 }
325
326 }
327}
328
329sub print_result_by_obj_size()
330{
331 return if (!%obj_info); #No obj info
332 # sort by ZI size
333 my @list = sort { $obj_info{$b}[1] <=> $obj_info{$a}[1] } keys %obj_info;
334
335 print "\n\n-->sort by obj ZI size<--\n\n";
336
337 if( 100 == $gnZIpercent )
338 {
339 print("Obj file\tSymbol\tVar size\tSize of total ZI in obj\n");
340 foreach my $strObjName (@list)
341 {
342 my $nObjZiSize = $obj_info{$strObjName}[0];
343
344 print "$strObjName\t \t \t$nObjZiSize\n";
345
346 for( my $i=2; $i<= $#{$obj_info{$strObjName}}; ++$i )
347 {
348 my $strVarName = $obj_info{$strObjName}[$i];
349 my $nVarSize = $var_info{$strVarName}[0];
350 print "\t$strVarName\t$nVarSize\n";
351 }
352 }
353 }
354 else
355 {
356 print("Obj file\tSymbol\tSymbol_size\tZI_Size\tRW_Size\tZI_percent\tSection\t\n");
357 foreach my $strObjName (@list)
358 {
359 my $nObjZiSize = $obj_info{$strObjName}[0];
360
361 print "$strObjName\tsize:$nObjZiSize\n";
362
363 for( my $i=2; $i<=$#{$obj_info{$strObjName}}; ++$i )
364 {
365 my $strVarName = $obj_info{$strObjName}[$i];
366 my $nVarSize = $var_info{$strVarName}[0];
367 my $nVarZISize = $var_info{$strVarName}[1];
368 my $strSection = $var_info{$strVarName}[3];
369
370 next if( !defined $nVarSize );
371 my $nVarRWSize = $nVarSize - $nVarZISize;
372 my $nVarZIpercent = $nVarZISize/$nVarSize*100;
373
374 print "\t $strVarName\t$nVarSize\t$nVarZISize\t$nVarRWSize\t$nVarZIpercent\t$strSection\n";
375 }
376 }
377
378 }
379}
380
381#calculate ROM base for L1core
382sub GenROMBase
383{
384 LinkerOutputParser::FileParse($sym_file);
385 my $ERs_aref = &LinkerOutputParser::ListAllExeRegion(1);
386 &detectZI_die("no any section?!") if( scalar(@$ERs_aref)==0 );
387 $gnROMBase = hex(&LinkerOutputParser::GetExeRegionInfo($ERs_aref->[0], Region::LMA));
388}
389
390sub detectZI_die
391{
392 my ($error_msg, $file, $line_no) = @_;
393 my $pack_name = undef;
394 if(!defined $file or !defined $line_no)
395 {
396 ($pack_name, $file, $line_no) = caller;
397 }
398 &CommonUtil::error_handler($error_msg, $file, $line_no, 'detectZI');
399}
400
401
402sub Usage
403{
404 print "version: $nVerion\n";
405 print <<"__EOFUSAGE";
406usage: perl $0 sym_file map_file elf_file ZI_percent ZI_threshold
407e.g. perl ./tools/MemoryUtility/DetectZI.pl \
408 ./build/PROHECT_NAME/FLAVOR/bin/AAA.sym \
409 ./build/PROHECT_NAME/FLAVOR/bin/AAA.map \
410 ./build/PROHECT_NAME/FLAVOR/bin/AAA.elf
411 100 \
412 0 \
413
414e.g. perl ./tools/MemoryUtility/DetectZI.pl \
415 ./build/PROHECT_NAME/FLAVOR/bin/AAA.sym \
416 ./build/PROHECT_NAME/FLAVOR/bin/AAA.map \
417 ./build/PROHECT_NAME/FLAVOR/bin/AAA.elf
418 90 \
419 1024 \
420
421__EOFUSAGE
422 exit 1;
423}
424
425