blob: fdfe5cc245c546c5c5c97a90a947ad8f9e761fa9 [file] [log] [blame]
yu.dongc33b3072024-08-21 23:14:49 -07001use strict;
2use warnings;
3#*--------------------------------------------------------------------------*
4#* Global variables
5#*--------------------------------------------------------------------------*
6my $LISFILE = $ARGV[0];
7my $DBGFILE = $ARGV[1];
8my %lang_pack_set;
9my %cust_pack_set;
10my %jump_table_set;
11my %lib_set;
12my %symbol_set;
13my %symbol_startaddr_set;
14my %symbol_endaddr_set;
15my %filesrange_set;
16my (@ref_sec, @dec_sec, @dec_region, @content, @total); # referencing obj, referencing function, declaration obj, declaraion region, referenced content
17my ($initialtime, $finishtime, $exectime);
18my $output = "";
19
20#*--------------------------------------------------------------------------*
21#* Code Body
22#*--------------------------------------------------------------------------*
23warn "
24==============================================================================
25 [Program] MBA_Check.pl
26 [Version] V2.0
27 [Date] 2011-12-01
28 [Author] yikuan.huang\@mediatek.com Timon.Lu\@mediatek.com
29 [Copyright] Copyright (C) 2011 MediaTek Incorporation. All Rights Reserved.
30==============================================================================
31";
32$initialtime = time();
33# parse the dbg file
34parsedbgfile();
35# parse the lis file
36parselisfile();
37# check the reference chain
38getFalseReference();
39# output result to file
40writeOutput();
41$finishtime = time();
42$exectime = $finishtime - $initialtime;
43print "Total execution time: ".$exectime." seconds\n";
44
45
46#****************************************************************************
47# FUNCTION
48# parsedbgfile
49# DESCRIPTION
50# This function parse DBG info file
51# if you need to know detail, please refer to DBG file format
52#****************************************************************************
53
54sub parsedbgfile{
55
56my $dbgfilesize = -s $ARGV[1];
57my ($mainversion, $subversion, $projectname, $hwversion, $swversion, $buildtime, $symtableoffset, $filetableoffset);
58my $symtablelength;
59my ($buf, $data, $n);
60my @contents;
61
62#-------------------------------------------------------------
63die "$DBGFILE does not exist!\n" if (!-e $DBGFILE);
64open (DBG_FILE_HANDLE, "<$DBGFILE") or die "Fail to open $DBGFILE\n";
65binmode DBG_FILE_HANDLE;
66#-------------------------------------------------------------
67$n = sysread (DBG_FILE_HANDLE, $data, $dbgfilesize);
68#------------------------parse header --------------------------
69if($data =~ /CATI(.{4})(.{4})([\w\s\x2E\x3A\x2F\x5F]+)\x00([\w\s\x2E\x3A\x2F\x5F]+)\x00([\w\s\x2E\x3A\x2F\x5F]+)\x00([\w\s\x2E\x3A\x2F\x5F]+)\x00(.{4})(.{4})([\s\S]*)/){
70 #mainversion of debug info
71 $mainversion = unpack('V', $1);
72 #subversion of debug info
73 $subversion = unpack('V', $2);
74 #project name of debug info
75 $projectname = $3;
76 #HW version of debug info
77 $hwversion = $4;
78 #SW version of debug info
79 $swversion = $5;
80 #build time of debug info which will be generated after building binary
81 $buildtime = $6;
82 #symtable offset of debug info which is append after debug info header (mainversion...etc)
83 $symtableoffset = unpack('V', $7);
84 #filetable offset of debug info which is append after symtable.
85 $filetableoffset = unpack('V', $8);
86
87 #debug info version match
88 if(($mainversion != 1) || ($subversion != 0)){
89 die "debug info file version is incorrect! VER_MAIN: ".$mainversion.", VER_SUB: ".$subversion."\n";
90 }
91 #get symbol table length
92 $symtablelength = $filetableoffset - $symtableoffset;
93 #truncate symbol table
94 $data = substr($9, 0, $symtablelength);
95
96 my $count = 3;
97 my $symbol;
98 #split symbol table by its format. name->null string->4 bytes for start addr->4 bytes for end addr ...repeat
99 my @symbols = split(/([\w:()]+).(.{4})(.{4})/, $data);
100 foreach my $val (@symbols) {
101 if(($count % 4 ) == 0){
102 #print length($val)." ".$val."\n";
103 $symbol = $val;
104 $symbol_set{$symbol} = $symbol;
105 }
106 elsif(($count % 4 ) == 1){
107 #print length($val)." ".unpack('V', $val)."\n";
108 $symbol_startaddr_set{$symbol} = unpack('V', $val);
109 }
110 elsif(($count % 4 ) == 2){
111 #print length($val)." ".unpack('V', $val)."\n";
112 $symbol_endaddr_set{$symbol} = unpack('V', $val);
113 }
114 $count++;
115 }
116 #truncate file table
117 $data = substr($9, $symtablelength+1);
118 $count = 1;
119 my $file_name="";
120 #split file table by its format. name->null string->4 bytes for number of addr range pair-> 4 bytes for
121 #pair one start addr->4 bytes for pair one end addr->......pair loop
122 #my @files = split(/([\w\x2F]+\x2F[\w]+).[c|cpp]\x00/, $data);
123 my @files = split(/\w+\x2F([\w]+).[c|cpp]\x00/, $data);
124 foreach my $val (@files) {
125 if($count % 2 == 0){
126 $file_name = $val;
127 #print $file_name."\n";
128 }
129 elsif($count % 2 == 1){
130 @contents = unpack("V*", $val);
131 $filesrange_set{$file_name} = [@contents];
132 }
133 $count++;
134 }
135}
136else{
137
138}
139
140close(DBG_FILE_HANDLE);
141
142}
143
144#****************************************************************************
145# FUNCTION
146# parselisfile
147# DESCRIPTION
148# This function parse LIS file
149#****************************************************************************
150sub parselisfile{
151my ($i, $ref_count);
152my $loadregionswitch = 0;
153my $langpackswitch = 0;
154my $custpackswitch = 0;
155my $jumptableswitch = 0;
156$i = 0;
157die "$LISFILE does not exist!\n" if (!-e $LISFILE);
158open (FILE_HANDLE, "<$LISFILE") or die "Fail to open $LISFILE\n";
159while (<FILE_HANDLE>) {
160 if (/(\S+)\..*\((\S+)\)\srefers\sto\s(\S+)\..*\((\S+)\)\sfor\s(\S+)\s*/) { # AAA.obj(i.func/pragma) refers to BBB.obj(i.func/pragma/region) for content
161 $ref_sec[$i] = $2.$1; # AAA
162 $dec_sec[$i] = $4.$3; # BBB
163 $total[$i] = $_;
164 $i++; # should be indexed with the same $i
165 }
166
167 if (/Memory Map of the image/){
168 $loadregionswitch = 1;
169 }
170 if (/Image component sizes/){
171 $loadregionswitch = 0;
172 }
173 # turn on the switch if meet Load Region LANG_PACK_ROM
174 if (/Execution Region LANG_PACK_ROM_CONTENT/){
175 $langpackswitch = 1;
176 }
177 else{
178 # turn off the switch if meet another Load Region
179 if (/Execution Region/){
180 $langpackswitch = 0;
181 }
182 }
183
184 # turn on the switch if meet Load Region CUSTPACK_ROM
185 if (/Execution Region CUSTPACK_ROM_CONTENT/){
186 $custpackswitch = 1;
187 }
188 else{
189 # turn off the switch if meet another Load Region
190 if (/Execution Region/){
191 $custpackswitch = 0;
192 }
193 }
194
195 # turn on the switch if meet Load Region JUMP_TABLE
196 if (/Load Region JUMP_TABLE/){
197 $jumptableswitch = 1;
198 }
199 else{
200 # turn off the switch if meet another Load Region
201 if (/Execution Region/){
202 $jumptableswitch = 0;
203 }
204 }
205
206 # parse the lang pack section
207 if ($langpackswitch == 1){
208 if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\w*)/){
209 unless(trim($1.$2) eq ""){
210 #print $2.$1."\n";
211 $lang_pack_set{$1.$2}=$1.$2;
212 }
213 }
214 }
215 # parse the cust pack section
216 if ($custpackswitch == 1){
217 if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\w*)/){
218 unless(trim($1.$2) eq ""){
219 $cust_pack_set{$1.$2}=$1.$2;
220 }
221 }
222 }
223 # parse the jump table section
224 if ($jumptableswitch == 1){
225 if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\w*)/){
226 unless(trim($1.$2) eq ""){
227 #print $2.$1."\n";
228 $jump_table_set{$1.$2}=$1.$2;
229 }
230 }
231 }
232 if ($loadregionswitch == 1){
233 #parse function
234 if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\S*)/){
235 my $section = $1;
236 my $objandLib = $2;
237 if($objandLib =~ /(\S*)\.o.*\((\S*)\)/){ #$2 = library name
238 $lib_set{$section.$1} = $2;
239 #print "$section -> $1 -> $2 \n";
240 }
241 }
242 }
243}
244close FILE_HANDLE or die "Fail to close $LISFILE\n";
245
246}
247#****************************************************************************
248# FUNCTION
249# replaceFileName
250# DESCRIPTION
251# this function use the result of parsedbgfile to get real file name!
252#
253#****************************************************************************
254sub replaceFileName{
255 my $filename = "";
256 my $libname = "";
257 my ($fromfunctionaddr, $tofunctionaddr, $fromfilename, $tofilename);
258
259 if($_[0] =~ /(\S+)\..*[\(\.]+(\w+)\)\srefers\sto\s(\S+)\..*[\(\.]+(\w+)\)\sfor\s(\S+)\s*/){
260 $fromfunctionaddr = $symbol_startaddr_set{$2}; # $2 = from function address
261 $tofunctionaddr = $symbol_startaddr_set{$4}; # $4 = to function address
262 # those two line are used to prevent warning msg.
263 $fromfunctionaddr = defined $fromfunctionaddr ? $fromfunctionaddr : 0;
264 $tofunctionaddr = defined $tofunctionaddr ? $tofunctionaddr : 0;
265 # look for file name by function address
266 for $filename (keys %filesrange_set){
267 if(length($filename) != 0){
268 for(my $i = 1; $i < ($filesrange_set{$filename}[0]*2+1); $i+=2){
269 if($fromfunctionaddr != 0 && $fromfunctionaddr >= $filesrange_set{$filename}[$i] && $fromfunctionaddr <= $filesrange_set{$filename}[$i+1]){
270 $fromfilename = $filename;
271 $_[0] =~ s/$1/$fromfilename/g;
272 }
273 if($tofunctionaddr != 0 && $tofunctionaddr >= $filesrange_set{$filename}[$i] && $tofunctionaddr <= $filesrange_set{$filename}[$i+1]){
274 $tofilename = $filename;
275 $_[0] =~ s/$3/$tofilename/g;
276 }
277 }
278 }
279 }
280 }
281 # those two line are used to prevent warning msg.
282 $fromfilename = defined $fromfilename ? $fromfilename : "";
283 $tofilename = defined $tofilename ? $tofilename : "";
284 $libname = $lib_set{$_[1]};
285 $libname = defined $libname ? $libname : "";
286 if(length($fromfilename) != 0){
287 $_[0] = "Warnning : $fromfilename.obj ($libname) \n ".$_[0];
288 }
289 else{
290 $_[0] = "Warnning : $1.obj ($libname) \n ".$_[0];
291 }
292}
293#****************************************************************************
294# FUNCTION
295# getFalseReference
296# DESCRIPTION
297# Check the function reference
298#****************************************************************************
299sub getFalseReference{
300
301for (my $i = 0;$i<@ref_sec;$i++) {
302 my $from_sec = $ref_sec[$i];
303 my $to_sec = $dec_sec[$i];
304 my $line = $total[$i];
305
306
307 # hard code to skip function InitializeResourceVariables and StandaloneResValidation
308 if(($from_sec =~ /resource_custpack_jtbl.*/) || ($from_sec =~ /resource_lang_pack_jtbl.*/)){
309 next;
310 }
311 # check if lang not refer to lang
312 if(isLangPack($from_sec) eq "true"){
313 unless(isLangPack($to_sec) eq "true"){
314 replaceFileName($line, $from_sec);
315 $output = $output.$line."Recommend Correction ---> Cannot Cross Reference Out of Lang Pack Content, Please Move RO-CODE out of RESB or Revise Data Structure\n\n";
316 }
317 }
318 # check if cust not refer to cust
319 if(isCustPack($from_sec) eq "true"){
320 unless(isCustPack($to_sec) eq "true"){
321 replaceFileName($line, $from_sec);
322 $output = $output.$line."Recommend Correction ---> Cannot Cross Reference Out of Cust Pack Content, Please Move RO-CODE out of RESB or Revise Data Structure\n\n";
323 }
324 }
325 # check if jtb not refer to lang or cust
326 if(isJumpTable($from_sec) eq "true"){
327 unless((isLangPack($to_sec) eq "true")||(isCustPack($to_sec) eq "true")){
328 replaceFileName($line, $from_sec);
329 $output = $output.$line."Recommend Correction ---> Critial Probelm, Please Reach System Service To Help You\n\n";
330 }
331 }
332 # check if not lang or jtb refer to lang
333 if(isLangPack($to_sec) eq "true"){
334 unless((isLangPack($from_sec) eq "true")||(isJumpTable($from_sec) eq "true")){
335 replaceFileName($line, $from_sec);
336 $output = $output.$line."Recommend Correction ---> Cannot Directly Reference To Lang Pack Content, Lookup JumpTable First\n\n";
337 }
338 }
339 # check if not cust or jtb refer to cust
340 if(isCustPack($to_sec) eq "true"){
341 unless((isCustPack($from_sec) eq "true")||(isJumpTable($from_sec) eq "true")){
342 replaceFileName($line, $from_sec);
343 $output = $output.$line."Recommend Correction ---> Cannot Directly Reference To Cust Pack Content, Lookup JumpTable First\n\n";
344 }
345 }
346 # check if lang or cust refer to jtb
347 if(isJumpTable($to_sec) eq "true"){
348 if((isLangPack($from_sec) eq "true")||(isCustPack($from_sec) eq "true")){
349 replaceFileName($line, $from_sec);
350 $output = $output.$line."Recommend Correction ---> Cannot Reverse Reference From RESB to Jump Table, Please Revise Data Structure\n\n";
351 }
352 }
353}
354
355}
356
357#****************************************************************************
358# FUNCTION
359# isLangPack
360# DESCRIPTION
361# Check the obj if exist in Lang Pack region
362#****************************************************************************
363sub isLangPack(){
364 my $result = "false";
365 my $obj = $_[0];
366 while ( my ($key, $value) = each(%lang_pack_set) ) {
367 my $target = $key;
368 if($obj eq $target){
369 $result = "true";
370 }
371 }
372 return $result;
373}
374#****************************************************************************
375# FUNCTION
376# isCustPack
377# DESCRIPTION
378# Check the obj if exist in Cust Pack region
379#****************************************************************************
380sub isCustPack(){
381 my $result = "false";
382 my $obj = $_[0];
383 while ( my ($key, $value) = each(%cust_pack_set) ) {
384 my $target = $key;
385 if($obj eq $target){
386 $result = "true";
387 }
388 }
389 return $result;
390}
391#****************************************************************************
392# FUNCTION
393# isJumpTable
394# DESCRIPTION
395# Check the obj if exist in Jump Table region
396#****************************************************************************
397sub isJumpTable(){
398 my $result = "false";
399 my $obj = $_[0];
400 while ( my ($key, $value) = each(%jump_table_set) ) {
401 my $target = $key;
402 if($obj eq $target){
403 $result = "true";
404 }
405 }
406 return $result;
407}
408#****************************************************************************
409# FUNCTION
410# writeOutput
411# DESCRIPTION
412# Output the result to file
413#****************************************************************************
414sub writeOutput{
415 # set the name of output file
416 my @part = split /\\/, $LISFILE;
417 my $outputFile = $part[-1];
418 $outputFile =~ s/lis/txt/;
419
420 #write result to file
421 open(RESULT,">$outputFile") || die "File open error!\n";
422 print RESULT $output;
423 close(RESULT)
424}
425
426#****************************************************************************
427# FUNCTION
428# trim
429# DESCRIPTION
430# Trim the space in front and back of string
431#****************************************************************************
432sub trim($)
433{
434 my $string = shift;
435 $string =~ s/^\s+//;
436 $string =~ s/\s+$//;
437 return $string;
438}