[Feature]Upload Modem source code
Change-Id: Id4294f30faced84d3e6fd6d5e61e1111bf287a37
diff --git a/mcu/tools/MBA_Check.pl b/mcu/tools/MBA_Check.pl
new file mode 100644
index 0000000..fdfe5cc
--- /dev/null
+++ b/mcu/tools/MBA_Check.pl
@@ -0,0 +1,438 @@
+use strict;
+use warnings;
+#*--------------------------------------------------------------------------*
+#* Global variables
+#*--------------------------------------------------------------------------*
+my $LISFILE = $ARGV[0];
+my $DBGFILE = $ARGV[1];
+my %lang_pack_set;
+my %cust_pack_set;
+my %jump_table_set;
+my %lib_set;
+my %symbol_set;
+my %symbol_startaddr_set;
+my %symbol_endaddr_set;
+my %filesrange_set;
+my (@ref_sec, @dec_sec, @dec_region, @content, @total); # referencing obj, referencing function, declaration obj, declaraion region, referenced content
+my ($initialtime, $finishtime, $exectime);
+my $output = "";
+
+#*--------------------------------------------------------------------------*
+#* Code Body
+#*--------------------------------------------------------------------------*
+warn "
+==============================================================================
+ [Program] MBA_Check.pl
+ [Version] V2.0
+ [Date] 2011-12-01
+ [Author] yikuan.huang\@mediatek.com Timon.Lu\@mediatek.com
+ [Copyright] Copyright (C) 2011 MediaTek Incorporation. All Rights Reserved.
+==============================================================================
+";
+$initialtime = time();
+# parse the dbg file
+parsedbgfile();
+# parse the lis file
+parselisfile();
+# check the reference chain
+getFalseReference();
+# output result to file
+writeOutput();
+$finishtime = time();
+$exectime = $finishtime - $initialtime;
+print "Total execution time: ".$exectime." seconds\n";
+
+
+#****************************************************************************
+# FUNCTION
+# parsedbgfile
+# DESCRIPTION
+# This function parse DBG info file
+# if you need to know detail, please refer to DBG file format
+#****************************************************************************
+
+sub parsedbgfile{
+
+my $dbgfilesize = -s $ARGV[1];
+my ($mainversion, $subversion, $projectname, $hwversion, $swversion, $buildtime, $symtableoffset, $filetableoffset);
+my $symtablelength;
+my ($buf, $data, $n);
+my @contents;
+
+#-------------------------------------------------------------
+die "$DBGFILE does not exist!\n" if (!-e $DBGFILE);
+open (DBG_FILE_HANDLE, "<$DBGFILE") or die "Fail to open $DBGFILE\n";
+binmode DBG_FILE_HANDLE;
+#-------------------------------------------------------------
+$n = sysread (DBG_FILE_HANDLE, $data, $dbgfilesize);
+#------------------------parse header --------------------------
+if($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]*)/){
+ #mainversion of debug info
+ $mainversion = unpack('V', $1);
+ #subversion of debug info
+ $subversion = unpack('V', $2);
+ #project name of debug info
+ $projectname = $3;
+ #HW version of debug info
+ $hwversion = $4;
+ #SW version of debug info
+ $swversion = $5;
+ #build time of debug info which will be generated after building binary
+ $buildtime = $6;
+ #symtable offset of debug info which is append after debug info header (mainversion...etc)
+ $symtableoffset = unpack('V', $7);
+ #filetable offset of debug info which is append after symtable.
+ $filetableoffset = unpack('V', $8);
+
+ #debug info version match
+ if(($mainversion != 1) || ($subversion != 0)){
+ die "debug info file version is incorrect! VER_MAIN: ".$mainversion.", VER_SUB: ".$subversion."\n";
+ }
+ #get symbol table length
+ $symtablelength = $filetableoffset - $symtableoffset;
+ #truncate symbol table
+ $data = substr($9, 0, $symtablelength);
+
+ my $count = 3;
+ my $symbol;
+ #split symbol table by its format. name->null string->4 bytes for start addr->4 bytes for end addr ...repeat
+ my @symbols = split(/([\w:()]+).(.{4})(.{4})/, $data);
+ foreach my $val (@symbols) {
+ if(($count % 4 ) == 0){
+ #print length($val)." ".$val."\n";
+ $symbol = $val;
+ $symbol_set{$symbol} = $symbol;
+ }
+ elsif(($count % 4 ) == 1){
+ #print length($val)." ".unpack('V', $val)."\n";
+ $symbol_startaddr_set{$symbol} = unpack('V', $val);
+ }
+ elsif(($count % 4 ) == 2){
+ #print length($val)." ".unpack('V', $val)."\n";
+ $symbol_endaddr_set{$symbol} = unpack('V', $val);
+ }
+ $count++;
+ }
+ #truncate file table
+ $data = substr($9, $symtablelength+1);
+ $count = 1;
+ my $file_name="";
+ #split file table by its format. name->null string->4 bytes for number of addr range pair-> 4 bytes for
+ #pair one start addr->4 bytes for pair one end addr->......pair loop
+ #my @files = split(/([\w\x2F]+\x2F[\w]+).[c|cpp]\x00/, $data);
+ my @files = split(/\w+\x2F([\w]+).[c|cpp]\x00/, $data);
+ foreach my $val (@files) {
+ if($count % 2 == 0){
+ $file_name = $val;
+ #print $file_name."\n";
+ }
+ elsif($count % 2 == 1){
+ @contents = unpack("V*", $val);
+ $filesrange_set{$file_name} = [@contents];
+ }
+ $count++;
+ }
+}
+else{
+
+}
+
+close(DBG_FILE_HANDLE);
+
+}
+
+#****************************************************************************
+# FUNCTION
+# parselisfile
+# DESCRIPTION
+# This function parse LIS file
+#****************************************************************************
+sub parselisfile{
+my ($i, $ref_count);
+my $loadregionswitch = 0;
+my $langpackswitch = 0;
+my $custpackswitch = 0;
+my $jumptableswitch = 0;
+$i = 0;
+die "$LISFILE does not exist!\n" if (!-e $LISFILE);
+open (FILE_HANDLE, "<$LISFILE") or die "Fail to open $LISFILE\n";
+while (<FILE_HANDLE>) {
+ 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
+ $ref_sec[$i] = $2.$1; # AAA
+ $dec_sec[$i] = $4.$3; # BBB
+ $total[$i] = $_;
+ $i++; # should be indexed with the same $i
+ }
+
+ if (/Memory Map of the image/){
+ $loadregionswitch = 1;
+ }
+ if (/Image component sizes/){
+ $loadregionswitch = 0;
+ }
+ # turn on the switch if meet Load Region LANG_PACK_ROM
+ if (/Execution Region LANG_PACK_ROM_CONTENT/){
+ $langpackswitch = 1;
+ }
+ else{
+ # turn off the switch if meet another Load Region
+ if (/Execution Region/){
+ $langpackswitch = 0;
+ }
+ }
+
+ # turn on the switch if meet Load Region CUSTPACK_ROM
+ if (/Execution Region CUSTPACK_ROM_CONTENT/){
+ $custpackswitch = 1;
+ }
+ else{
+ # turn off the switch if meet another Load Region
+ if (/Execution Region/){
+ $custpackswitch = 0;
+ }
+ }
+
+ # turn on the switch if meet Load Region JUMP_TABLE
+ if (/Load Region JUMP_TABLE/){
+ $jumptableswitch = 1;
+ }
+ else{
+ # turn off the switch if meet another Load Region
+ if (/Execution Region/){
+ $jumptableswitch = 0;
+ }
+ }
+
+ # parse the lang pack section
+ if ($langpackswitch == 1){
+ if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\w*)/){
+ unless(trim($1.$2) eq ""){
+ #print $2.$1."\n";
+ $lang_pack_set{$1.$2}=$1.$2;
+ }
+ }
+ }
+ # parse the cust pack section
+ if ($custpackswitch == 1){
+ if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\w*)/){
+ unless(trim($1.$2) eq ""){
+ $cust_pack_set{$1.$2}=$1.$2;
+ }
+ }
+ }
+ # parse the jump table section
+ if ($jumptableswitch == 1){
+ if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\w*)/){
+ unless(trim($1.$2) eq ""){
+ #print $2.$1."\n";
+ $jump_table_set{$1.$2}=$1.$2;
+ }
+ }
+ }
+ if ($loadregionswitch == 1){
+ #parse function
+ if(/\s*0x\S*\s*\S*\s*\S*\s*\S*\s*\S*\s*(\S*)\s*(\S*)/){
+ my $section = $1;
+ my $objandLib = $2;
+ if($objandLib =~ /(\S*)\.o.*\((\S*)\)/){ #$2 = library name
+ $lib_set{$section.$1} = $2;
+ #print "$section -> $1 -> $2 \n";
+ }
+ }
+ }
+}
+close FILE_HANDLE or die "Fail to close $LISFILE\n";
+
+}
+#****************************************************************************
+# FUNCTION
+# replaceFileName
+# DESCRIPTION
+# this function use the result of parsedbgfile to get real file name!
+#
+#****************************************************************************
+sub replaceFileName{
+ my $filename = "";
+ my $libname = "";
+ my ($fromfunctionaddr, $tofunctionaddr, $fromfilename, $tofilename);
+
+ if($_[0] =~ /(\S+)\..*[\(\.]+(\w+)\)\srefers\sto\s(\S+)\..*[\(\.]+(\w+)\)\sfor\s(\S+)\s*/){
+ $fromfunctionaddr = $symbol_startaddr_set{$2}; # $2 = from function address
+ $tofunctionaddr = $symbol_startaddr_set{$4}; # $4 = to function address
+ # those two line are used to prevent warning msg.
+ $fromfunctionaddr = defined $fromfunctionaddr ? $fromfunctionaddr : 0;
+ $tofunctionaddr = defined $tofunctionaddr ? $tofunctionaddr : 0;
+ # look for file name by function address
+ for $filename (keys %filesrange_set){
+ if(length($filename) != 0){
+ for(my $i = 1; $i < ($filesrange_set{$filename}[0]*2+1); $i+=2){
+ if($fromfunctionaddr != 0 && $fromfunctionaddr >= $filesrange_set{$filename}[$i] && $fromfunctionaddr <= $filesrange_set{$filename}[$i+1]){
+ $fromfilename = $filename;
+ $_[0] =~ s/$1/$fromfilename/g;
+ }
+ if($tofunctionaddr != 0 && $tofunctionaddr >= $filesrange_set{$filename}[$i] && $tofunctionaddr <= $filesrange_set{$filename}[$i+1]){
+ $tofilename = $filename;
+ $_[0] =~ s/$3/$tofilename/g;
+ }
+ }
+ }
+ }
+ }
+ # those two line are used to prevent warning msg.
+ $fromfilename = defined $fromfilename ? $fromfilename : "";
+ $tofilename = defined $tofilename ? $tofilename : "";
+ $libname = $lib_set{$_[1]};
+ $libname = defined $libname ? $libname : "";
+ if(length($fromfilename) != 0){
+ $_[0] = "Warnning : $fromfilename.obj ($libname) \n ".$_[0];
+ }
+ else{
+ $_[0] = "Warnning : $1.obj ($libname) \n ".$_[0];
+ }
+}
+#****************************************************************************
+# FUNCTION
+# getFalseReference
+# DESCRIPTION
+# Check the function reference
+#****************************************************************************
+sub getFalseReference{
+
+for (my $i = 0;$i<@ref_sec;$i++) {
+ my $from_sec = $ref_sec[$i];
+ my $to_sec = $dec_sec[$i];
+ my $line = $total[$i];
+
+
+ # hard code to skip function InitializeResourceVariables and StandaloneResValidation
+ if(($from_sec =~ /resource_custpack_jtbl.*/) || ($from_sec =~ /resource_lang_pack_jtbl.*/)){
+ next;
+ }
+ # check if lang not refer to lang
+ if(isLangPack($from_sec) eq "true"){
+ unless(isLangPack($to_sec) eq "true"){
+ replaceFileName($line, $from_sec);
+ $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";
+ }
+ }
+ # check if cust not refer to cust
+ if(isCustPack($from_sec) eq "true"){
+ unless(isCustPack($to_sec) eq "true"){
+ replaceFileName($line, $from_sec);
+ $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";
+ }
+ }
+ # check if jtb not refer to lang or cust
+ if(isJumpTable($from_sec) eq "true"){
+ unless((isLangPack($to_sec) eq "true")||(isCustPack($to_sec) eq "true")){
+ replaceFileName($line, $from_sec);
+ $output = $output.$line."Recommend Correction ---> Critial Probelm, Please Reach System Service To Help You\n\n";
+ }
+ }
+ # check if not lang or jtb refer to lang
+ if(isLangPack($to_sec) eq "true"){
+ unless((isLangPack($from_sec) eq "true")||(isJumpTable($from_sec) eq "true")){
+ replaceFileName($line, $from_sec);
+ $output = $output.$line."Recommend Correction ---> Cannot Directly Reference To Lang Pack Content, Lookup JumpTable First\n\n";
+ }
+ }
+ # check if not cust or jtb refer to cust
+ if(isCustPack($to_sec) eq "true"){
+ unless((isCustPack($from_sec) eq "true")||(isJumpTable($from_sec) eq "true")){
+ replaceFileName($line, $from_sec);
+ $output = $output.$line."Recommend Correction ---> Cannot Directly Reference To Cust Pack Content, Lookup JumpTable First\n\n";
+ }
+ }
+ # check if lang or cust refer to jtb
+ if(isJumpTable($to_sec) eq "true"){
+ if((isLangPack($from_sec) eq "true")||(isCustPack($from_sec) eq "true")){
+ replaceFileName($line, $from_sec);
+ $output = $output.$line."Recommend Correction ---> Cannot Reverse Reference From RESB to Jump Table, Please Revise Data Structure\n\n";
+ }
+ }
+}
+
+}
+
+#****************************************************************************
+# FUNCTION
+# isLangPack
+# DESCRIPTION
+# Check the obj if exist in Lang Pack region
+#****************************************************************************
+sub isLangPack(){
+ my $result = "false";
+ my $obj = $_[0];
+ while ( my ($key, $value) = each(%lang_pack_set) ) {
+ my $target = $key;
+ if($obj eq $target){
+ $result = "true";
+ }
+ }
+ return $result;
+}
+#****************************************************************************
+# FUNCTION
+# isCustPack
+# DESCRIPTION
+# Check the obj if exist in Cust Pack region
+#****************************************************************************
+sub isCustPack(){
+ my $result = "false";
+ my $obj = $_[0];
+ while ( my ($key, $value) = each(%cust_pack_set) ) {
+ my $target = $key;
+ if($obj eq $target){
+ $result = "true";
+ }
+ }
+ return $result;
+}
+#****************************************************************************
+# FUNCTION
+# isJumpTable
+# DESCRIPTION
+# Check the obj if exist in Jump Table region
+#****************************************************************************
+sub isJumpTable(){
+ my $result = "false";
+ my $obj = $_[0];
+ while ( my ($key, $value) = each(%jump_table_set) ) {
+ my $target = $key;
+ if($obj eq $target){
+ $result = "true";
+ }
+ }
+ return $result;
+}
+#****************************************************************************
+# FUNCTION
+# writeOutput
+# DESCRIPTION
+# Output the result to file
+#****************************************************************************
+sub writeOutput{
+ # set the name of output file
+ my @part = split /\\/, $LISFILE;
+ my $outputFile = $part[-1];
+ $outputFile =~ s/lis/txt/;
+
+ #write result to file
+ open(RESULT,">$outputFile") || die "File open error!\n";
+ print RESULT $output;
+ close(RESULT)
+}
+
+#****************************************************************************
+# FUNCTION
+# trim
+# DESCRIPTION
+# Trim the space in front and back of string
+#****************************************************************************
+sub trim($)
+{
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ return $string;
+}