blob: 0ed8c2e72218db5758605268880a8d60fe8f69e5 [file] [log] [blame]
rjw6c1fd8f2022-11-30 14:33:01 +08001#*--------------------------------------------------------------------------*
2#* Global variables
3#*--------------------------------------------------------------------------*
4my $LISFILE = $ARGV[0];
5my $rootdir = @ARGV[1];
6my $mcudir = @ARGV[2];
7my $branch = @ARGV[3];
8my @filearray;
9my @disarray;
10my @unusedroarray;
11my @resultarray;
12my @symbolarray;
13my $printmode = "dec";
14my $outputfilename;
15my $unusedfilename;
16#*--------------------------------------------------------------------------*
17#* Code Body
18#*--------------------------------------------------------------------------*
19
20$initialtime = time();
21
22warn "
23==============================================================================
24 [Program] ROParser.pl
25 [Version] V3.0
26 [Date] 2008-04-09
27 [Author] yikuan.huang\@mediatek.com
28 [Copyright] Copyright (C) 2008 MediaTek Incorporation. All Rights Reserved.
29==============================================================================
30";
31
32unless(defined($branch)){
33 usage();
34}
35startview($branch);
36determinefilename();
37print "start to parse LIS file......\n";
38parselisfile();
39print "finish parsing LIS file......\n";
40
41print "start to disassemble...\n";
42traversefile($rootdir);
43disassemble();
44print "finish disassembling!\n";
45
46print "start to get unusedRO...\n";
47getunusedRO();
48print "finish getting unusedRO...\n";
49
50print "start to parse dis file...\n";
51parsedisfile();
52print "finish parsing dis file...\n";
53
54print "start to dump resule to files...\n";
55dump_resulte_to_file();
56print "finish dumping resule to files!\n";
57
58$finishtime = time();
59$exectime = $finishtime - $initialtime;
60print "Total execution time: ".$exectime." seconds\n";
61
62
63
64#****************************************************************************
65# FUNCTION
66# determinefilename
67# DESCRIPTION
68# This function determine the name of output file
69#****************************************************************************
70sub determinefilename{
71 @filepart = split /\\/,$LISFILE;
72 $outputfilename = $filepart[-1];
73 $unusedfilename = $filepart[-1];
74 if($filepart[-1] =~ /(\S+)lis/){
75 $outputfilename = $1;
76 }
77 $unusedfilename = $outputfilename;
78 $outputfilename = $outputfilename."txt";
79 $unusedfilename =~ s/\.//;
80 $unusedfilename = $unusedfilename."unusedRO.txt";
81}
82#****************************************************************************
83# FUNCTION
84# parselisfile
85# DESCRIPTION
86# This function parse LIS file
87#****************************************************************************
88sub parselisfile{
89#****************************************************************************
90# Parse LIS file content
91#****************************************************************************
92my (@ref_obj, @ref_func, @dec_obj, @dec_region, @content , @symbol); # referencing obj, referencing function, declaration obj, declaraion region, referenced content
93my ($i, $ref_count ,$j, $switch);
94
95die "$LISFILE does not exist!\n" if (!-e $LISFILE);
96
97
98open (FILE_HANDLE, "<$LISFILE") or die "Fail to open $LISFILE\n";
99$i = 0;
100$j = 0;
101$switch = 0;
102while (<FILE_HANDLE>) {
103 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
104 $ref_obj[$i] = $1; # AAA
105 $ref_func[$i] = $2; # i.func/pragma
106 $dec_obj[$i] = $3; # BBB
107 $dec_region[$i] = $4; # i.func/pragma/region
108 $content[$i] = $5; # content
109 $i++; # should be indexed with the same $i
110 }
111 if (/Local Symbols/){
112 $switch = 1;
113 }
114 if (/================================================================================/){
115 $switch = 0;
116 }
117 if ($switch == 1){
118 $_ = trim($_);
119 if(/(\S+)(\s*)(\S+)(\s*)(\S+)(\s*)(\S+)(\s*)(\S+)/){
120 $symbol[$j] = $1;
121 $j++;
122 }
123 }
124}
125$ref_count = $i;
126close FILE_HANDLE or die "Fail to close $LISFILE\n";
127
128@symbol = reverse sort @symbol;
129
130#****************************************************************************
131# Further parse the reference table to find constdata
132#****************************************************************************
133my $ref_data;
134my %constdata;
135$i = 0;
136foreach $ref_data (@content) {
137 if ($ref_data eq ".constdata\$1") { # AAA.obj(i.func/pragma) refers to BBB.obj(i.func/pragma/region) for .constdata$1
138 $constdata{$i} = $ref_data; # constdata{$i} = .constdata$1, $i is the index of constdata references
139 }
140 $i++;
141}
142
143
144#****************************************************************************
145# Find unused RO data
146#****************************************************************************
147my (%unused_RO_func, %unused_RO_pragma);
148
149$i = 0;
150while ($i < $ref_count) {
151 if (defined $constdata{$i}) {
152 my $is_In_Symbol_Table = 0;
153 my $funcname = $ref_func[$i];
154 foreach (@symbol){
155 my $tablefuncname = $_;
156 if($funcname eq $tablefuncname){
157 $is_In_Symbol_Table = 1;
158 last;
159 }
160 if($funcname gt $tablefuncname){
161 $is_In_Symbol_Table = 0;
162 last;
163 }
164 }
165 if ($is_In_Symbol_Table == 0) {
166 if ($ref_func[$i] =~ /i.(\S+)/) { # function case
167 $unused_RO_func{$ref_func[$i]} = $ref_obj[$i];
168 }
169 else{
170 $unused_RO_pragma{$ref_func[$i]} = $ref_obj[$i];
171 }
172 #print $ref_func[$i]."...".$ref_obj[$i]."\n";
173 }
174 }
175 $i++;
176}
177
178#****************************************************************************
179# Output unreferenced functions that contain unused RO data
180#****************************************************************************
181open (FILE_HANDLE, ">$unusedfilename") or die "Fail to open $unusedfilename\n";
182my $ref_data;
183print FILE_HANDLE "Unreferenced functions that contain unused RO data: \n";
184foreach $ref_data (sort {$unused_RO_func{$a} cmp $unused_RO_func{$b}} keys %unused_RO_func) {
185 print FILE_HANDLE "$ref_data ($unused_RO_func{$ref_data})\n";
186}
187
188print FILE_HANDLE "\nOther pragmas that contains unreferenced functions with RO data: \n";
189foreach $ref_data (sort {$unused_RO_pragma{$a} cmp $unused_RO_pragma{$b}} keys %unused_RO_pragma) {
190 print FILE_HANDLE "$ref_data ($unused_RO_pragma{$ref_data})\n";
191}
192
193close FILE_HANDLE or die "Fail to close output.txt\n";
194
195
196}
197
198
199
200#****************************************************************************
201# FUNCTION
202# dump_resulte_to_file
203# DESCRIPTION
204# This function dumps the result of RO parser to file(result.txt)
205#****************************************************************************
206sub dump_resulte_to_file{
207 #*--------------------------------------------------------------------------*
208 #* Local variables
209 #*--------------------------------------------------------------------------*
210 $resultfuncname;
211 $resultobjname;
212 $resultconstantstring;
213 $resultstringsize;
214 $resultconstantdata;
215 $resultdatasize;
216 $resultfilepath;
217 $resultowner;
218 #*--------------------------------------------------------------------------*
219 #* Code Body
220 #*--------------------------------------------------------------------------*
221 %ownerhash;
222 open(RESULT,">$outputfilename") || die "File open error!\n";
223 # Set the data format
224format RESULT =
225 @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<< @<<<<<<<<<<
226 $resultfuncname,$resultobjname,$resultconstantstring,$resultstringsize,$resultconstantdata,$resultdatasize,$resultowner
227.
228 foreach (@resultarray){
229 my $resulthash = $_;
230 $resultfuncname = $resulthash->{"funcname"};
231 $resultobjname = $resulthash->{"objname"};
232 $resultconstantstring = $resulthash->{"constantstring"};
233 $resultstringsize = $resulthash->{"stringsize"};
234 $resultconstantdata = $resulthash->{"constantdata"};
235 $resultdatasize = $resulthash->{"datasize"};
236 $resultfilepath = get_objpath_by_objname($resultobjname);
237 if(defined $ownerhash{$resultfilepath}){
238
239 }
240 else{
241 $ownerhash{$resultfilepath} = getOwner($resultfilepath);
242 }
243 $resultowner = $ownerhash{$resultfilepath};
244 if($printmode eq "dec"){
245 if($resultstringsize =~ /0x(\w+)/){
246 $resultstringsize = hex($1);
247 }
248 if($resultdatasize =~ /0x(\w+)/){
249 $resultdatasize = hex($1);
250 }
251 }
252 #print $resultfuncname." ".$resultobjname." ".$resultconstantstring." ".$resultstringsize." ".$resultconstantdata." ".$resultdatasize."\n";
253 write(RESULT);
254 }
255 close(RESULT);
256
257 #delete unusedRO file
258 #unlink($unusedfilename);
259}
260
261#****************************************************************************
262# FUNCTION
263# check_global_table
264# DESCRIPTION
265# This function check whether the offset is in the global symbol table
266#****************************************************************************
267sub check_global_table(){
268 $_ = $_[0];
269 s/0x//;
270 my $offset = hex($_);
271 my $objname = $_[1];
272 my $result = "0";
273 #print $offset." ... ".$objname."\n";
274 foreach (@symbolarray){
275 my $symbolhash = $_;
276 $symbolojbname = $symbolhash->{"objname"};
277 $symbolname = $symbolhash->{"symbolname"};
278 $symbolvalue = $symbolhash->{"symbolvalue"};
279 $symbolsize = $symbolhash->{"symbolsize"};
280 $symbolstart = $symbolhash->{"symbolstart"};
281 $symbolend = $symbolhash->{"symbolend"};
282 if($symbolojbname eq $objname){
283 if(($offset>=$symbolstart) && ( $offset<$symbolend)){
284 $result = $symbolname.":".$symbolsize;
285 last;
286 }
287 }
288 }
289 return $result;
290}
291
292
293#****************************************************************************
294# FUNCTION
295# parsedisfile
296# DESCRIPTION
297# This function parse the dis file which appears in @unusedroarray , and create the result
298#****************************************************************************
299sub parsedisfile(){
300 #*--------------------------------------------------------------------------*
301 #* Code Body
302 #*--------------------------------------------------------------------------*
303 foreach (@unusedroarray){
304 my $gethash = $_;
305 my $getobjname = $gethash->{"objname"};
306 my $getfuncname = $gethash->{"funcname"};
307 my $getdisfilepath = $gethash->{"disfilepath"};
308 my $firstaddress;
309 my $offset;
310 my $constdatasecnum;
311 if(defined($getdisfilepath)){
312 @symbolarray = ();
313 open(FILE,"<$getdisfilepath") || die "File open error - $getdisfilepath!\n";
314 @data = <FILE>;
315 my $funcswitch = 0;
316 my $getoffset = 0;
317 my $findconstdatasec = 0;
318 my $constdataswitch = 0;
319 my $hasvalue = 0;
320
321
322 my $thisoffset;
323 my $targetoffset;
324
325 my $hasequal = 0;
326
327 my @blockarray;
328 my @indexarray;
329 my @firstaddressarray;
330 my $index = 0;
331 my $targetindex = 0;
332 my $maxlength = 16;
333
334 my $hasglobal = 0;
335
336 #&parse_for_global_symbol_table(@data);
337 my $currentsecnum; #store section number temporarily
338 my @secnum; #store section number in one dis file
339 #****************************************************************************
340 # 1 >>> First round : scan the dis file, and get all the section number which has .constdata
341 # For example, ** Section #10
342 #
343 # Name : .constdata
344 # We find the ".constdata", and get it's previous section number - 10
345 # Store all the section number into @secnum
346 #****************************************************************************
347 foreach(@data){
348 # Find each section number, and record it in the $currentsecnum
349 if($_ =~ /\*\* Section #(\d+)/){
350 $currentsecnum = $1;
351 }
352 # Find the .constdata, record the previous section number into @secnum
353 if(index($_,"Name : .constdata")>=0){
354 push @secnum, $currentsecnum;
355 }
356 }
357
358 #****************************************************************************
359 # 2 >>> Second round : scan the dis file, get the data row from the symbol table
360 # For example,
361 # Symbol table .symtab (121 symbols, 112 local)
362 # Symbol Name Value Bind Sec Type Size
363 # ========================================================================
364 # 1 $t 0x00000000 Lc 5 Code
365 # ................................
366 # ========================================================================
367 #
368 # We find "Symbol table" first, and record the data between two "=======" lines
369 #****************************************************************************
370 $isSym = 0;
371 $switch = 0;
372
373 foreach(@data){
374 # Find the symbol table
375 if(index($_,"Symbol table .symtab")>=0){
376 $isSym = 1;
377 next;
378 }
379 if((index($_,"=================")>=0)&&($isSym eq 1)){
380 $switch = 1;
381 $isSym = 0;
382 next;
383 }
384 if((index($_,"==================")>=0)&&($isSym eq 0)){
385 $switch = 0;
386 next;
387 }
388 if($switch eq 1){
389 my %symbolhash;
390 #if it has 7 values
391 if(/\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/){
392 #print $1."\n".$2."\n".$3."\n".$4."\n".$5."\n".$6."\n".$7."\n";
393 #print "\n";
394 if(matchsecnum($5,@secnum) eq 1){
395 %symbolhash ={};
396 $symbolhash{"objname"}= $getobjname;
397 $symbolhash{"symbolname"}= $2;
398 $symbolhash{"symbolvalue"}= $3;
399 $symbolhash{"symbolsize"}= $7;
400 if(index($symbolhash{"symbolsize"},"0x")>=0){
401 $_ = $symbolhash{"symbolvalue"};
402 s/0x//;
403 $symbolhash{"symbolstart"} = hex($_);
404 $_ = $symbolhash{"symbolsize"};
405 s/0x//;
406 $symbolhash{"symbolend"} = $symbolhash{"symbolstart"} + hex($_);
407 push @symbolarray, \%symbolhash;
408 }
409 }
410 next;
411 }
412 #if it has 6 values
413 elsif(/\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/){
414 #print $1."\n".$2."\n".$3."\n".$4."\n".$5."\n".$6."\n";
415 #print "\n";
416 if(matchsecnum($5,@secnum) eq 1){
417 %symbolhash ={};
418 $symbolhash{"objname"}= $getobjname;
419 $symbolhash{"symbolname"}= $2;
420 $symbolhash{"symbolvalue"}= $3;
421 }
422 next;
423 }
424
425 # across two line!!
426 else{
427 # second line: 5 values
428 if(/\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/){
429 #print $1."\n".$2."\n".$3."\n".$4."\n".$5."\n";
430 if(matchsecnum($3,@secnum) eq 1){
431 $symbolhash{"objname"}= $getobjname;
432 $symbolhash{"symbolvalue"}= $1;
433 $symbolhash{"symbolsize"}= $5;
434 if(index($symbolhash{"symbolsize"},"0x")>=0){
435 $_ = $symbolhash{"symbolvalue"};
436 s/0x//;
437 $symbolhash{"symbolstart"} = hex($_);
438 $_ = $symbolhash{"symbolsize"};
439 s/0x//;
440 $symbolhash{"symbolend"} = $symbolhash{"symbolstart"} + hex($_);
441 push @symbolarray, \%symbolhash;
442 }
443 %symbolhash ={};
444 }
445 next;
446 }
447 # second line: 4 values
448 if(/\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/){
449 #print $1."\n".$2."\n".$3."\n".$4."\n";
450 if(matchsecnum($3,@secnum) eq 1){
451 $symbolhash{"objname"}= $getobjname;
452 $symbolhash{"symbolvalue"}= $1;
453 if(index($symbolhash{"symbolsize"},"0x")>=0){
454 $_ = $symbolhash{"symbolvalue"};
455 s/0x//;
456 $symbolhash{"symbolstart"} = hex($_);
457 $_ = $symbolhash{"symbolsize"};
458 s/0x//;
459 $symbolhash{"symbolend"} = $symbolhash{"symbolstart"} + hex($_);
460 push @symbolarray, \%symbolhash;
461 }
462 %symbolhash ={};
463 }
464 next;
465 }
466 # first line: 2 values
467 if(/\s+(\S+)\s+(\S+)/){
468 #print $1."\n".$2."\n";
469 $symbolhash{"symbolname"}= $2;
470 next
471 }
472 }
473 }
474
475 }
476
477
478
479 foreach(@data){
480 # open the section
481 if($_ =~ /Name : i.$getfuncname\n/){
482 $funcswitch = 1;
483 $findconstdatasec = 1;
484 next;
485 }
486 if($_ =~ /Name : $getfuncname\n/){
487 $funcswitch = 1;
488 $findconstdatasec = 1;
489 next;
490 }
491
492 if(($funcswitch == 1)&&($_ =~ /.constdata$1/)){
493 # if the address has 4 digits
494 $isExist = "false";
495 if($_ =~ /= 0x(\w\w\w\w)]/){
496 $firstaddress = $1;
497 foreach $address(@firstaddressarray){
498 if($address eq $firstaddress){
499 $isExist = "true";
500 }
501 }
502 if($isExist eq "false"){
503 push @firstaddressarray, $firstaddress;
504 }
505 next;
506 }
507 # if the address has 3 digits
508 if($_ =~ /= 0x(\w\w\w)]/){
509 $firstaddress = $1;
510 foreach $address(@firstaddressarray){
511 if($address eq $firstaddress){
512 $isExist = "true";
513 }
514 }
515 if($isExist eq "false"){
516 push @firstaddressarray, $firstaddress;
517 }
518 next;
519 }
520 # if the address has 2 digits
521 if($_ =~ /= 0x(\w\w)]/){
522 $firstaddress = $1;
523 foreach $address(@firstaddressarray){
524 if($address eq $firstaddress){
525 $isExist = "true";
526 }
527 }
528 if($isExist eq "false"){
529 push @firstaddressarray, $firstaddress;
530 }
531 next;
532 }
533 # if the address has 1 digits
534 if($_ =~ /= 0x(\w)]/){
535 $firstaddress = $1;
536 foreach $address(@firstaddressarray){
537 if($address eq $firstaddress){
538 $isExist = "true";
539 }
540 }
541 if($isExist eq "false"){
542 push @firstaddressarray, $firstaddress;
543 }
544 next;
545 }
546 }
547 # close the section
548 if(($funcswitch == 1)&&index($_,"====================================") >= 0){
549 $funcswitch = 0;
550 }
551 }
552
553
554#print $getdisfilepath."\n";
555#print @firstaddressarray."\n";
556foreach(@firstaddressarray){
557 $firstaddress = $_;
558 $stringlength = 0;
559 $stringresult = "";
560 foreach(@data){
561 # open the section
562 if($_ =~ /Name : i.$getfuncname\n/){
563 $funcswitch = 1;
564 $findconstdatasec = 1;
565 next;
566 }
567 if($_ =~ /Name : $getfuncname\n/){
568 $funcswitch = 1;
569 $findconstdatasec = 1;
570 next;
571 }
572 if(($funcswitch == 1)&&($firstaddress ne "")&&($_ =~ /0x0+$firstaddress:/)){
573 my @linearray = split;
574 if($linearray[1] =~ /00(\S+)/){
575 $offset = "0x".$1;
576 $getoffset = 1;
577 # check whether the offset is in the global symbol table
578 $returndata = &check_global_table($offset,$getobjname);
579
580 unless($returndata eq "0"){
581 my %resulthash ={};
582 $resulthash{"funcname"}= $getfuncname;
583 $resulthash{"objname"}= $getobjname;
584 if($returndata =~ /(\S+):(\S+)/){
585 $resulthash{"constantdata"} = $1;
586 $resulthash{"datasize"}= $2;
587 }
588 push @resultarray, \%resulthash;
589 $hasglobal = 1;
590 last;
591 }
592 next;
593 }
594 }
595 # close the section
596 if(($funcswitch == 1)&&index($_,"====================================") >= 0){
597 $funcswitch = 0;
598 }
599
600 # find the section number of .constdata
601 if(($findconstdatasec == 1)&&(index($_,".constdata$1")>=0)){
602 if(/#(\d+) '.constdata'/){
603 $constdatasecnum = $1;
604 $findconstdatasec = 0;
605 next;
606 }
607
608 }
609 # find .constdata block
610 if(($getoffset==1)&&($_ =~ /\*\* Section #${constdatasecnum}$/)){
611 $constdataswitch = 1;
612 #$getoffset == 0;
613 next;
614 }
615
616
617
618 # find the string in the .constdata block
619 if(($constdataswitch == 1)&&($_ =~ /0x(\S+):/)){
620 # if match the offset
621 if(index($_,$offset.":")>=0){
622 $hasequal = 1;
623 $targetindex = $index;
624 }
625
626 push @indexarray,$index;
627 push @blockarray,trim($_);
628 $index++;
629 }
630
631 if(($constdataswitch == 1)&&(index($_,"====================================") >= 0)){
632 $constdataswitch = 0;
633 }
634 }
635
636 if($hasglobal == 1){
637 next;
638 }
639 if($getoffset == 0){
640 $resulthash{"funcname"}= $getfuncname;
641 $resulthash{"objname"}= "(".$getobjname.")";
642 push @resultarray, \%resulthash;
643 next;
644 }
645
646 # start to parse the block data
647
648 # if find the offset match the target offset
649 if($hasequal == 1){
650 $line = trim($blockarray[$targetindex]);
651 $moreswitch = 1;
652 #$stringlength = 0;
653 while($moreswitch == 1){
654 @stringarray = split /\s+/,$line;
655 # remove the first and last item
656 shift(@stringarray);
657 pop(@stringarray);
658 $thislength = 0;
659 if(scalar(@stringarray) == 0){
660 $moreswitch = 0;
661 }
662 foreach $hexvalue(@stringarray){
663 if(is_ascii($hexvalue)){
664 $thislength++;
665 if($thislength <= $maxlength){
666 $stringresult = $stringresult.hex_to_ascii($hexvalue);
667 }
668 # need to consider next line
669 if($thislength == $maxlength){
670 $targetindex = $targetindex + 1;
671 if($targetindex < scalar(@blockarray)){
672 $line = trim($blockarray[$targetindex]);
673 $stringlength += $thislength;
674 }
675 }
676
677 }
678 else{
679 if(($hexvalue eq "00")&&($stringlength != 0)){
680 $stringlength += 1;
681 }
682 $stringlength += $thislength;
683 $moreswitch = 0;
684 last;
685 }
686 }
687 }
688 # save the result
689 my %resulthash ={};
690 if($stringlength > 0){
691 $resulthash{"funcname"}= $getfuncname;
692 $resulthash{"objname"}= $getobjname;
693 $resulthash{"constantstring"} = $stringresult;
694 $resulthash{"stringsize"}= "0x".dec2hex($stringlength);
695 }
696 else{
697 $resulthash{"funcname"}= "(".$getfuncname.")";
698 $resulthash{"objname"}= $getobjname;
699 }
700 push @resultarray, \%resulthash;
701 }
702
703 # if no offset match the target offset
704 else{
705 my $findbetween = 0;
706 for($i=0;$i<@blockarray;$i++){
707 $line = trim($blockarray[$i]);
708 $nextarget = $i;
709 @stringarray = split /\s+/,$line;
710 # get the offset value of this line
711 $_ = shift(@stringarray);
712 s/0x//;
713 $thisoffset = hex($_);
714 # get the offset value of next line
715 $nextoffset = 0;
716 if($i != (@blockarray-1)){
717 @temparray = split /\s+/,trim($blockarray[$i+1]);
718 $_ = shift(@temparray);
719 s/0x//;
720 $nextoffset = hex($_);
721 }
722 # get the target offset
723 $_ = $offset;
724 s/0x//;
725 $targetoffset = hex($_);
726
727 $difference = $targetoffset - $thisoffset;
728
729 if(($targetoffset > $thisoffset)&&($targetoffset < $nextoffset)){
730
731 $findbetween = 1;
732 $moreswitch = 0;
733 #$stringlength = 0;
734 @stringarray = split /\s+/,$line;
735 # remove the first and last item
736 shift(@stringarray);
737 pop(@stringarray);
738 # remove the first different items
739 for($j=0;$j<$difference;$j++){
740 shift(@stringarray);
741 }
742 $thislength = 0;
743 $moreswitch = 0;
744 foreach $hexvalue(@stringarray){
745 if(is_ascii($hexvalue)){
746 $thislength++;
747 if($thislength <= ($maxlength-$difference)){
748 $stringresult = $stringresult.hex_to_ascii($hexvalue);
749 }
750 # need to consider next line
751 if($thislength == ($maxlength-$difference)){
752 $nextarget = $nextarget + 1;
753 if($nextarget < scalar(@blockarray)){
754 $line = trim($blockarray[$nextarget]);
755 $moreswitch = 1;
756 $stringlength += $thislength;
757 }
758 }
759
760 }
761 else{
762 if(($hexvalue eq "00")&&($stringlength != 0)){
763 $stringlength += 1;
764 }
765 $stringlength += $thislength;
766 $moreswitch = 0;
767 last;
768 }
769 }
770 while($moreswitch == 1){
771 @stringarray = split /\s+/,$line;
772 # remove the first and last item
773 shift(@stringarray);
774 pop(@stringarray);
775 $thislength = 0;
776 if(scalar(@stringarray) == 0){
777 $moreswitch = 0;
778 }
779 foreach $hexvalue(@stringarray){
780 if(is_ascii($hexvalue)){
781 $thislength++;
782 if($thislength <= $maxlength){
783 $stringresult = $stringresult.hex_to_ascii($hexvalue);
784 }
785 # need to consider next line
786 if($thislength == $maxlength){
787 $nextarget = $nextarget + 1;
788 if($nextarget < @blockarray){
789 $line = trim($blockarray[$nextarget]);
790 $stringlength += $thislength;
791 }
792 }
793
794 }
795 else{
796 if(($hexvalue eq "00")&&($stringlength != 0)){
797 $stringlength += 1;
798 }
799 $stringlength += $thislength;
800 $moreswitch = 0;
801 last;
802 }
803 }
804 }
805 # save the result
806 my %resulthash ={};
807 if($stringlength > 0){
808 $resulthash{"funcname"}= $getfuncname;
809 $resulthash{"objname"}= $getobjname;
810 $resulthash{"constantstring"} = $stringresult;
811 $resulthash{"stringsize"}= "0x".dec2hex($stringlength);
812 }
813 else{
814 $resulthash{"funcname"}= "(".$getfuncname.")";
815 $resulthash{"objname"}= $getobjname;
816 }
817 push @resultarray, \%resulthash;
818 last;
819 }
820 }
821 # if no offset is between two offsets
822 if($findbetween == 0){
823 if($#blockarray != -1){
824 $line = trim($blockarray[$#blockarray]);
825 @stringarray = split /\s+/,$line;
826 # get the offset value of this line
827 $_ = shift(@stringarray);
828 s/0x//;
829 $thisoffset = hex($_);
830 # get the target offset
831 $_ = $offset;
832 s/0x//;
833 $targetoffset = hex($_);
834 # calculate the difference
835 $difference = $targetoffset - $thisoffset;
836 # remove the first and last item
837 shift(@stringarray);
838 pop(@stringarray);
839 # remove the first different items
840 for($j=0;$j<$difference;$j++){
841 shift(@stringarray);
842 }
843 foreach $hexvalue(@stringarray){
844 if(is_ascii($hexvalue)){
845 $stringlength++;
846 if($stringlength <= ($maxlength-$difference)){
847 $stringresult = $stringresult.hex_to_ascii($hexvalue);
848 }
849 }
850 }
851 # save the result
852 my %resulthash ={};
853 if($stringlength > 0){
854 $resulthash{"funcname"}= $getfuncname;
855 $resulthash{"objname"}= $getobjname;
856 $resulthash{"constantstring"} = $stringresult;
857 $resulthash{"stringsize"}= "0x".dec2hex($stringlength);
858 }
859 else{
860 $resulthash{"funcname"}= "(".$getfuncname.")";
861 $resulthash{"objname"}= $getobjname;
862 }
863 push @resultarray, \%resulthash;
864 }
865 }
866
867 }
868
869
870
871} #close for firstaddressarray
872 close(FILE);
873 }
874 }
875}
876#****************************************************************************
877# FUNCTION
878# getunusedRO
879# DESCRIPTION
880# Parse unusedRO.txt, and get the function name and obj filename
881#****************************************************************************
882sub getunusedRO{
883 #*--------------------------------------------------------------------------*
884 #* Code Body
885 #*--------------------------------------------------------------------------*
886 open(FILE,"<$unusedfilename") || die "File open error!\n";
887
888 @data = <FILE>;
889 foreach(@data){
890 #skip the line that contains :
891 if(index($_,":") >= 0){
892 next;
893 }
894 # Find each section number, and record it in the $currentsecnum
895 if($_ =~ /(\S+)\s\((\S+)\)/){
896 #print $1." ".$2."\n";
897 my %unusedrohash ={};
898 $unusedrohash{"funcname"}= $1;
899 $unusedrohash{"objname"}= $2;
900 $unusedrohash{"disfilepath"} = get_dispath_by_objname($2);
901 push @unusedroarray, \%unusedrohash;
902 }
903 }
904 close(FILE);
905
906}
907
908#****************************************************************************
909# FUNCTION
910# get_dispath_by_objname
911# DESCRIPTION
912# Find the corresponding disfile by obj name
913#****************************************************************************
914sub get_dispath_by_objname(){
915 #*--------------------------------------------------------------------------*
916 #* Local variables
917 #*--------------------------------------------------------------------------*
918 my $objname = $_[0];
919 #*--------------------------------------------------------------------------*
920 #* Code Body
921 #*--------------------------------------------------------------------------*
922 foreach (@disarray){
923 my $gethash = $_;
924 my $getobjname = $gethash->{"objname"};
925 my $getdisfilepath = $gethash->{"disfilepath"};
926 #if($objname =~ /(\S+).o$/){
927 # $objname = $1.".obj";
928 #}
929
930 if($getobjname eq $objname){
931 return $getdisfilepath;
932 }
933 }
934 return undef;
935}
936
937#****************************************************************************
938# FUNCTION
939# get_objpath_by_objname
940# DESCRIPTION
941# Find the corresponding objfile by obj name
942#****************************************************************************
943sub get_objpath_by_objname(){
944 #*--------------------------------------------------------------------------*
945 #* Local variables
946 #*--------------------------------------------------------------------------*
947 my $objname = $_[0];
948 #*--------------------------------------------------------------------------*
949 #* Code Body
950 #*--------------------------------------------------------------------------*
951 foreach (@disarray){
952 my $gethash = $_;
953 my $getobjname = $gethash->{"objname"};
954 my $getobjfilepath = $gethash->{"objfilepath"};
955 #if($objname =~ /(\S+).o$/){
956 # $objname = $1.".obj";
957 #}
958
959 if($getobjname eq $objname){
960 return $getobjfilepath;
961 }
962 }
963 return undef;
964}
965#****************************************************************************
966# FUNCTION
967# dimp_symboltable_to_file
968# DESCRIPTION
969# This function dumps the the data of symbolarray to file(symboltable.txt)
970#****************************************************************************
971sub dump_symboltable_to_file{
972 #*--------------------------------------------------------------------------*
973 #* Local variables
974 #*--------------------------------------------------------------------------*
975 my $disfilename;
976 my $symbolname;
977 my $symbolvalue;
978 my $symbolsize;
979
980 #*--------------------------------------------------------------------------*
981 #* Code Body
982 #*--------------------------------------------------------------------------*
983 open(FILE,">symboltable.txt") || die "File open error!\n";
984
985 # Set the data format
986format FILE =
987 @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<< @<<<<<<<<<<
988 $disfilename,$symbolname, $symbolvalue,$symbolsize
989.
990 foreach (@symbolarray){
991 my $symbolhash = $_;
992 $disfilename = $symbolhash->{"objname"};
993 $symbolname = $symbolhash->{"symbolname"};
994 $symbolvalue = $symbolhash->{"symbolvalue"};
995 $symbolsize = $symbolhash->{"symbolsize"};
996 # Remove the empty line
997 unless($symbolname eq ""){
998 write(FILE);
999 }
1000 }
1001 close(FILE);
1002}
1003
1004#****************************************************************************
1005# FUNCTION
1006# matchsecnum
1007# DESCRIPTION
1008# This function determine whether the section number is in the secnum array
1009# PARAMETERS
1010# $secnum section number
1011# @secnumarray section number array
1012# RETURNS
1013# result return 1 for success; return 0 for fail
1014#****************************************************************************
1015sub matchsecnum{
1016 #*--------------------------------------------------------------------------*
1017 #* Local variables
1018 #*--------------------------------------------------------------------------*
1019 my $result = 0;
1020 my $secnum = $_[0];
1021 my @secnumarray = $_[1];
1022 #*--------------------------------------------------------------------------*
1023 #* Code Body
1024 #*--------------------------------------------------------------------------*
1025 foreach (@secnumarray){
1026 if($secnum == $_){
1027 $result = 1;
1028 return $result;
1029 }
1030 }
1031 return $result;
1032}
1033sub trim($)
1034{
1035 my $string = shift;
1036 $string =~ s/^\s+//;
1037 $string =~ s/\s+$//;
1038 return $string;
1039}
1040#****************************************************************************
1041# FUNCTION
1042# disassemble
1043# DESCRIPTION
1044# This function disassemble all the obj files in the root directory
1045#****************************************************************************
1046sub disassemble{
1047 foreach (@filearray){
1048 #*--------------------------------------------------------------------------*
1049 #* Local variables
1050 #*--------------------------------------------------------------------------*
1051 my $myhash = $_;
1052 my $filename = $myhash->{"filename"};
1053 my $filepath = $myhash->{"filepath"};
1054 #*--------------------------------------------------------------------------*
1055 #* Code Body
1056 #*--------------------------------------------------------------------------*
1057 $_ = $filename;
1058 s/.obj/.dis/;
1059 my $newfilename = $_;
1060 $_ = $filepath;
1061 s/$filename/$newfilename/;
1062
1063 #Start to Disassemble (obj=>dis)
1064
1065 #If the dis file doesn't exist, disassemble the obj file
1066 unless(-e $_){
1067 #system("start C:\\Progra~1\\ARM\\ADSv1_2\\Bin\\fromelf -cdrstvz ".$myhash->{"filepath"}.">".$_);
1068 system("C:\\Progra~1\\ARM\\ADSv1_2\\Bin\\fromelf -cdrstvz ".$myhash->{"filepath"}.">".$_);
1069 print "C:\\Progra~1\\ARM\\ADSv1_2\\Bin\\fromelf -cdrstvz ".$myhash->{"filepath"}.">".$_."\n";
1070 #sleep(1);
1071 }
1072
1073 my %filehash ={};
1074 $filehash{"objname"}= $filename;
1075 $filehash{"objfilepath"}= $filepath;
1076 $filehash{"disfilepath"}= $_;
1077 push @disarray, \%filehash;
1078
1079}
1080
1081
1082}
1083
1084
1085#****************************************************************************
1086# FUNCTION
1087# traversefile
1088# DESCRIPTION
1089# This function scan the root directory , find all the obj files
1090# PARAMETERS
1091# #sub_DIR root directory
1092#****************************************************************************
1093 sub traversefile{
1094 #*--------------------------------------------------------------------------*
1095 #* Local variables
1096 #*--------------------------------------------------------------------------*
1097 my $sub_DIR_id ;
1098 my $sub_DIR ;
1099 my $sub_SRC_FILE;
1100 my @dirarray;
1101 my $i;
1102 my $count=0;
1103 my $newdir;
1104
1105 $sub_DIR = $_[0]; # root directory
1106 #*--------------------------------------------------------------------------*
1107 #* Code Body
1108 #*--------------------------------------------------------------------------*
1109
1110 #if $sub_DIR is a directory
1111 if(-d ($sub_DIR)){
1112 opendir(sub_DIR_id, $sub_DIR) or die " cannot open directory :($sub_DIR)\n";
1113 while ( defined ($sub_SRC_FILE = readdir(sub_DIR_id)) )
1114 {
1115 #exclude . and ..
1116 if (($sub_SRC_FILE ne "\.") && ($sub_SRC_FILE ne "\.\."))
1117 {
1118 my $path = $sub_DIR."\\".$sub_SRC_FILE;
1119 unless(-d ($path)){
1120 $_ = $path;
1121 #Only count obj file
1122 if(/.obj$/i){
1123 my %filehash ={};
1124 $filehash{"filename"}= $sub_SRC_FILE;
1125 $filehash{"filepath"}= $path;
1126 push @filearray, \%filehash;
1127 }
1128 }
1129 @dirarray[$count]=$sub_DIR."\\".$sub_SRC_FILE;
1130 $count++;
1131 }
1132 }
1133 for($i=0;$i<$count;$i++){
1134 $newdir = @dirarray[$i];
1135 traversefile($newdir);
1136 }
1137 }
1138#****************************************************************************
1139# FUNCTION
1140# hex_to_ascii
1141# DESCRIPTION
1142# This function convert each two-digit hex number back to an ASCII character
1143#****************************************************************************
1144sub hex_to_ascii ($){
1145 (my $str = shift) =~ s/([a-fA-F0-9]{2})/chr(hex $1)/eg;
1146 return $str;
1147}
1148#****************************************************************************
1149# FUNCTION
1150# is_ascii
1151# DESCRIPTION
1152# This function check whether the param is a ascii code
1153#****************************************************************************
1154sub is_ascii($){
1155 $param = hex_to_ascii($_[0]);
1156 $asciinum = ord($param);
1157 if((($asciinum>=32)&&($asciinum<=126))||($asciinum==10)){
1158 return 1;
1159 }
1160 else{
1161 return 0;
1162 }
1163}
1164
1165 sub dec2hex {
1166 # parameter passed to
1167 # the subfunction
1168 my $decnum = $_[0];
1169 # the final hex number
1170 my $hexnum;
1171 my $tempval;
1172 while ($decnum != 0) {
1173 # get the remainder (modulus function)
1174 # by dividing by 16
1175 $tempval = $decnum % 16;
1176 # convert to the appropriate letter
1177 # if the value is greater than 9
1178 if ($tempval > 9) {
1179 $tempval = chr($tempval + 55);
1180 }
1181 # 'concatenate' the number to
1182 # what we have so far in what will
1183 # be the final variable
1184 $hexnum = $tempval . $hexnum ;
1185 # new actually divide by 16, and
1186 # keep the integer value of the
1187 # answer
1188 $decnum = int($decnum / 16);
1189 # if we cant divide by 16, this is the
1190 # last step
1191 if ($decnum < 16) {
1192 # convert to letters again..
1193 if ($decnum > 9) {
1194 $decnum = chr($decnum + 55);
1195 }
1196
1197 # add this onto the final answer..
1198 # reset decnum variable to zero so loop
1199 # will exit
1200 $hexnum = $decnum . $hexnum;
1201 $decnum = 0
1202 }
1203 }
1204 return $hexnum;
1205 } # end sub
1206
1207
1208
1209}
1210
1211sub getOwner(){
1212 $cc_mcu_path = "M:\\".$branch."_int\\MAUI_SW\\mcu";
1213 $fullfilepath = shift @_;
1214 @part = split /\\/,$fullfilepath;
1215 $obj_parse = $part[-1];
1216 $lib_parse = $part[-2].".lib";
1217 $owner = "";
1218 $filepath = getfilepath($lib_parse,$obj_parse,$mcudir);
1219
1220 if($mcudir eq ".\\"){
1221 $_ = $filepath;
1222 s/.\\/\\/;
1223 $cc_mcu_path = $cc_mcu_path.$_;
1224 }
1225 else{
1226 if($filepath =~ /(\S+)mcu(\S+)/){
1227 $cc_mcu_path = $cc_mcu_path.$2;
1228 }
1229 }
1230
1231 if (!-e ){
1232 $new_cc_mcu_path = $cc_mcu_path."pp";
1233 if (-e $new_cc_mcu_path){
1234 $cc_mcu_path = $new_cc_mcu_path;
1235 }
1236 }
1237 $owner = get_owner_from_CC_server($cc_mcu_path);
1238 return $owner;
1239}
1240sub getfilepath
1241{
1242 my ($mcu_path, $lis_path);
1243 $lib_file = shift @_;
1244 $obj_file = shift @_;
1245 $mcu_path = shift @_;
1246 my ($lib_tmp, $obj_tmp);
1247
1248 ### get lis file path
1249 $lib_file =~ /(.*).lib/;
1250 $lib_tmp = $1;
1251
1252 # search source file path for object file
1253 # query from lis file
1254
1255
1256 if ((lc($lib_file) eq "conn_app.lib")||(lc($lib_file) eq "inet_app.lib")||(lc($lib_file) eq "mmi_app.lib")||(lc($lib_file) eq "mmi_framework.lib")||(lc($lib_file) eq "media_app.lib")) ## find file path in the official release code base
1257 {
1258 $lis_path = $mcu_path . "make\\plutommi\\$lib_tmp\\$lib_tmp.lis";
1259 }
1260 else
1261 {
1262 $lis_path = $mcu_path . "make\\$lib_tmp\\$lib_tmp.lis";
1263 }
1264
1265 ### get c file path
1266 $obj_file =~ /(.*).obj/;
1267 $obj_tmp = $1;
1268
1269 my $c_file = "$obj_tmp" . ".c";
1270
1271 my $success = open (LIS_FILE, "<$lis_path") or warn "cannot open $lis_path\n";
1272
1273 if($success)
1274 {
1275 # read whole file
1276 my $backup = $/;
1277 undef $/;
1278 my $reading = <LIS_FILE>;
1279 $/ = $backup;
1280
1281 if ($reading =~ /(.*\\)$c_file/i)
1282 {
1283 #print "HIT2: $1\n";
1284 $c_file = $mcu_path. $1 . $c_file;
1285 #print "C_FILE: $c_file\n";
1286 }
1287 else
1288 {
1289 print "Assert: $c_file is NOT MATCHED in $lis_path !\n";
1290 }
1291 }
1292
1293 return $c_file;
1294}
1295
1296
1297#****************************************************************************
1298# Get owner of the source of a label from CC server
1299# Support when file is merged from subsidiary branch
1300#****************************************************************************
1301sub get_owner_from_CC_server
1302{
1303 my ($src) = @_;
1304 my $result;
1305 my $CQ_owner;
1306 my $cmd1;
1307 my $tmp3;
1308 my $tmp4;
1309 my $tmp5;
1310 my $cmd2=();
1311
1312 if($src=~/(.+)\\(.+)/g )
1313 {
1314 $tmp3=$1;
1315 $tmp4=$2;
1316 my $file_name;
1317
1318 $tmp5="M: & cd ".$tmp3." & ";
1319
1320 $tmp4=~s/\./\\\./;
1321 if(!(-d $tmp3))
1322 {
1323 $CQ_owner="ccadmin";
1324 return $CQ_owner;
1325 }
1326
1327 #opendir (TMP3_DIR, $tmp3) or die "can't open directory $tmp3: $!";
1328 opendir (TMP3_DIR, $tmp3);
1329 while ( defined ($file_name = readdir(TMP3_DIR)) )
1330 {
1331 if ($file_name=~/^$tmp4$/i)
1332 {
1333 $tmp4=$file_name;
1334 last;
1335 }
1336 }
1337 closedir TMP3_DIR;
1338 $cmd2=();
1339
1340 $cmd2=$tmp5.'cleartool describe -fmt "Onwer: %Lu\nActivity: %[activity]p\n"'." ".$tmp4;
1341
1342 $result=`$cmd2`;
1343 }
1344
1345 if($result=~/Onwer: (.+)\.Domain Users/i)
1346 {
1347 $CQ_owner=$1;
1348 if($CQ_owner=~/ccadmin/i)
1349 {
1350 $cmd2=();
1351 $cmd2=$tmp5."cleartool describe ".$tmp4."\|find \"Merge\"";
1352
1353 $result=`$cmd2`;
1354 if($result=~/Merge <- ([^\s]+)/i)
1355 {
1356 $tmp4=$1;
1357
1358 $cmd2='cleartool describe -fmt "Onwer: %Lu\nActivity: %[activity]p\n"'." ".$tmp4;
1359 $result=`$cmd2`;
1360 if($result=~/Onwer: (.+)\.Domain Users/i)
1361 {
1362 $CQ_owner=$1;
1363 #print "Merge file owner:$CQ_owner \n";
1364 }
1365 }
1366 }
1367 }
1368 return $CQ_owner;
1369} # sub get_owner_from_CC_server
1370
1371
1372sub usage
1373{
1374 print "perl ROParser.pl <LIS filepath> <obj root path> <mcu path> <branch>\n";
1375 exit(0);
1376}
1377
1378sub startview(){
1379 $view = $branch."_int";
1380 $result = `cleartool startview $view 2>&1`;
1381 print $result;
1382 if($result =~ /cleartool: Error:/){
1383 exit(0);
1384 }
1385}