blob: 4ef8ea20dbae5a337b695836d8faa11f6bcbce81 [file] [log] [blame]
#!/usr/bin/perl
#
# Copyright Statement:
# --------------------
# This software is protected by Copyright and the information contained
# herein is confidential. The software may not be copied and the information
# contained herein may not be used or disclosed except with the written
# permission of MediaTek Inc. (C) 2012
#
# BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
# THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
# RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
# AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
# NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
# SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
# SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
# THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
# NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
# SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
#
# BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
# LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
# AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
# OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
# MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
#
# THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
# WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
# LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
# RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
# THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
#
#*****************************************************************************
#*
#* Filename:
#* ---------
#* ckLDS.pl
#*
#* Project:
#* --------
#*
#*
#* Description:
#* ------------
#* This script is to check memory layout
#*
#* Author:
#* -------
#* Qmei Yang (mtk03726)
#*
#****************************************************************************/
#****************************************************************************
# Included Modules
#****************************************************************************
BEGIN { push @INC , './tools/', './tools/MemoryUtility/' } # add additional library path
use strict;
use File::Basename;
use FileInfoParser;
use CommonUtility;
use LinkerOutputParser;
use ldsInfo;
#****************************************************************************
# Constants
#****************************************************************************
#LDS Type
use constant MAIN => 0;
use constant BL => 1;
use constant EXT_BL => 2;
#CORE Type
use constant PCORE_TYPE => 0;
use constant L1CORE_TYPE => 1;
# The following constant patterns are used in m notify for finding the corresponding owner.
# If any change, you have to sync with ErrorMsg Handler BM for the modification information.
use constant INVALID_OBJECT_LIST => "- INVALID OBJECT LIST -";
use constant ERROR_HANDLING_SOP => "- ERROR HANDLING SOP -";
#****************************************************************************
# VERNO
#****************************************************************************
my $CKLDS_VERNO = " u0.02";
# u0.02 by Carl, 20150225, Refactor for L1core
# u0.01 by Carl, 20141023, Memory Utility Refinement
# m0.04 by mei, Remove warning messages
# m0.03 by mei, Show invalid regions even if it contains no objlist
# m0.02 by mei, Parse linker script directly and output formal error message
# m0.01 by JI , initial version
#****************************************************************************
# Input Parameters and Global Variables
#****************************************************************************
my $phase = $ARGV[0];
my $g_stop_build = $ARGV[1];
my $g_LDSInputPath = $ARGV[2];
my $map_file = $ARGV[3];
my $FLASH_CFG_TMP = $ARGV[4]; # XXX Not Used in current version
my $g_MakeFilePath = $ARGV[5]; # XXX Not Used in current version
my $BB_FOLDER = $ARGV[6]; # XXX Not Used in current version
my $DUMMY_LDS_ALLOW = $ARGV[7]; # XXX Not Used in current version
#****************************************************************************
# 0 >>> parse input parameters and decide ckscatter phase
#****************************************************************************
if ($phase == 1)
{
#warn "ckLDS: phase 1 not implemented yet\n";
}
elsif ($phase == 2)
{
&cklds_phase2($map_file, $g_LDSInputPath);
}
else
{
&error_handler("Unsupported ckMemLayout command!");
}
exit 0;
#****************************************************************************
# 1 >>> Phase 1
#****************************************************************************
#****************************************************************************
# 2 >>> Phase 2
#****************************************************************************
sub cklds_phase2
{
my ($LinkerOutput_MAP, $LDS) = @_;
my $SYM_ERList = &ParseLinkerOutput_SYM($LinkerOutput_MAP);
my $LDS_ERList = &ParseLinkerInput($LDS);
my $SYMOddRegions_href = &CompareER($SYM_ERList, $LDS_ERList);
if (keys(%$SYMOddRegions_href) > 0)
{
&LinkerOutputParser::FileParse($LinkerOutput_MAP);
my $InvalidER_href = &GetOddObjList($SYMOddRegions_href);
my $err_msg .= &Get_Template_Caution();
$err_msg .= "------------------- INVALID SECTION LIST -------------------\n";
$err_msg .= &Get_Template_DiffER_In_SYM_but_Not_in_LDS($InvalidER_href) . "\n";
$err_msg .= "------------------".INVALID_OBJECT_LIST."-------------------\n";
$err_msg .= &Get_Template_InvalidObjList($InvalidER_href);
my $nLDSType = &GetLDSType($LDS);
my $nCoreType = &GetCoreType($LDS);
$err_msg .= &Get_Template_ErrorHandlingSOP($nLDSType, $nCoreType);
&error_handler($err_msg, 1);
}
}
#****************************************************************************
# subroutine: GetOddObjList
# used in cklds_phase2()
# input : Region_href
# return: \%ObjList: {ER}=> \@ObjList
#****************************************************************************
sub GetOddObjList
{ # Check Linker Output Diff Regions , which object inside
my ($SYMOddRegions_href) = @_;
my %OddObjList; # RegionName => [obj1, obj2...]
foreach my $ER (sort keys %$SYMOddRegions_href)
{
my $Offender_objlist = &LinkerOutputParser::GetObjByExeRegion($ER);
$OddObjList{$ER} = $Offender_objlist;
}
return \%OddObjList;
}
#****************************************************************************
# subroutine: ParseLinkerInput: Retrieve Execution Regions from linker script
# used in cklds_phase2()
# input : strLDSFilePath
# return: \@ER_List: Execution Region Array
#****************************************************************************
sub ParseLinkerInput
{
my ($strldsFilePath) = @_;
my $Info = new ldsInfo;
$Info->ParseLinkerScript($strldsFilePath);
my $ERList_aref = $Info->GetAllExeRegion();
my $HiddenERList_aref = $Info->GetAllHiddenExeRegion();
push (@$ERList_aref , @$HiddenERList_aref);
&error_handler("Input($strldsFilePath) is not correct!") if (!defined $ERList_aref);
#print "=================[LDS]=====================\n";
#map {print "$_\n";} @$ERList_aref;
#print "======================================\n";
return $ERList_aref;
}
#****************************************************************************
# subroutine: ParseLinkerOutput_SYM: Retrieve Execution Regions from Linker Output Parser
# used in cklds_phase2()
# input : strMapFilePath
# => it'll be transferred to sym file inside the function
# return: \@ER_List: Execution Region Array
#****************************************************************************
sub ParseLinkerOutput_SYM
{
my ($strMAPPath) = @_;
my $ERList_aref = undef;
my $sym_file = $strMAPPath;
$sym_file =~ s/\.map$/\.sym/; #execution region information is not supported in LinkerOutputParser.pm while the input is .map
&LinkerOutputParser::FileParse($sym_file);
my $ERList_aref = &LinkerOutputParser::ListAllExeRegion();
&error_handler("Input or LinkerOutputParser.pm is not correct!") if (!defined $ERList_aref);
#print "=================[SYM]=====================\n";
#map {print "$_\n";} @$ERList_aref;
#print "======================================\n";
return $ERList_aref;
}
#****************************************************************************
# subroutine: CompareER: Compare 2 region list
# used in cklds_phase2()
# input : $SYM_ERList: an array reference
# $LDS_ERList: an array reference
# return: \%Region List: a hash contains the regions in sym but not in lds
#****************************************************************************
sub CompareER
{
my ($SYM_ERList, $LDS_ERList) = @_; # array_ref
my %Out_left; #used to get SYM Left Strange Regions
my @Out_Same;
my %LDSERHash;
map{$LDSERHash{$_} = 1;}@$LDS_ERList;
foreach my $ER (@$SYM_ERList)
{
next if($ER eq "");
if (exists $LDSERHash{$ER})
{
push @Out_Same, $ER;
delete $LDSERHash{$ER};
}
else
{
$Out_left{$ER} = 1;
}
}
&TrimDebugRegions(\%Out_left);
#&Print_LDS_ERList_Not_In_SYM(\%LDSERHash);
#&Print_SameER_In_SYM_and_LDS(\@Out_Same);
return \%Out_left;
}
#****************************************************************************
# subroutine: TrimDebugRegions: Normal GCC Regions for Debugging
# used in CompareER()
# input : $SYM_ERList: a hash reference contains regions in sym
# return: N/A
#****************************************************************************
sub TrimDebugRegions
{
my ($ERList_href) = @_;
foreach my $ER (sort keys %$ERList_href)
{ #------ Normal GCC Regions for Debugging -----
if ($ER =~ /^\.debug_/
or $ER =~ /^\.ARM\.attributes/
or $ER =~ /^\.comment/
or $ER =~ /^\.stab/)
{
#print $ER, "\n";
delete $ERList_href->{$ER};
}
}
}
#****************************************************************************
# subroutine: GetCoreType
# input: $strLDSPath : LDS FilePath
# return: CORE Type: PCORE_TYPE, L1CORE_TYPE
#****************************************************************************
sub GetCoreType
{
my ($strLDSPath) = @_;
if($strLDSPath =~/l1core/i)
{
return L1CORE_TYPE;
}
else
{
return PCORE_TYPE;
}
}
#****************************************************************************
# subroutine: GetLDSType
# input: $strLDSPath : LDS FilePath
# return: LDSType: MAIN, BL, EXT_BL
#****************************************************************************
sub GetLDSType
{
my ($strLDSPath) = @_;
my $strName = basename($strLDSPath);
if($strName =~/ldsBL.*\_ext\./i)
{
return EXT_BL;
}
elsif($strName =~/ldsBL.*\./i)
{
return BL;
}
else
{
return MAIN;
}
}
#****************************************************************************
# subroutine: Get_Template_DiffER_In_SYM_but_Not_in_LDS
# input: $SYMER_href: a hash reference contains regions in sym but not in lds
# return: Template shown in log file: regions in sym but not in lds
#****************************************************************************
sub Get_Template_DiffER_In_SYM_but_Not_in_LDS
{
my ($SYMER_href) = @_;
my $template;
#------ Linker Output Found Strange Regions --------;
map{$template .= "$_\n";}sort keys %$SYMER_href;
return $template;
}
#****************************************************************************
# subroutine: Get_Template_InvalidObjList
# input: $OddList_href: a hash reference contains regions in sym but not in lds
# return: Template shown in log file, e.g.
# |1. Objects as below are wrapped in invalid section(C$$code):
# |ex_hdlr_gcc.obj
# |stack_gcc.obj
# |
#****************************************************************************
sub Get_Template_InvalidObjList
{
my ($OddList_href) = @_;
my $template;
my $i=1;
foreach my $ER(sort keys %$OddList_href)
{
#####################################################################################
# The following pattern($ER) is used in m notify for finding the corresponding owner.
# If any change, you have to sync with ErrorMsg Handler BM for the modification information.
$template .= "$i. Objects as below are wrapped in invalid section($ER):\n";
#####################################################################################
map{ $template.= $_."\n";} @{$OddList_href->{$ER}};
$template.= "\n";
$i++;
}
return $template;
}
sub Print_LDS_ERList_Not_In_SYM
{
my ($LDSER_href) = @_;
print "------ LDSRegionList not in SYM -------\n";
map{print "$_\n";}sort keys %$LDSER_href;
}
sub Print_SameER_In_SYM_and_LDS
{
my ($ER_aref) = @_;
print "------ The Same RegionList in SYM and LDS -------\n";
map{print "$_\n";} @$ER_aref;
}
#****************************************************************************
# subroutine: error_handler
# input : $error_msg
# $bPrintDirectly: undef or 0=using formal format to show error message,
# 1=print error message directly without adding any other message
# return: none
#****************************************************************************
sub error_handler
{
my ($error_msg, $bPrintDirectly) = @_;
my $todie = $g_stop_build;
my ($pack_name, $file, $line_no) = caller;
my $final_error_msg = ($bPrintDirectly) ? $error_msg: "CKMEMLAYOUT ERROR: \n$error_msg\nat $file line $line_no\n";
print $final_error_msg if ($todie ne 'TRUE');
die $final_error_msg if ($todie eq 'TRUE');
}
sub Get_Template_ErrorHandlingSOP
{
my ($nLdsType, $nCoreType) = @_;
my $title = ERROR_HANDLING_SOP;
my $template= "-------------------$title--------------------\n";;
my $strPath = &GetSOPPath($nLdsType, $nCoreType);
if(-e $strPath)
{
$template .= &CommonUtil::GetFileContent($strPath) . "\n";
}
else
{
$template .= "Please refer to $strPath\n\n";
}
$template .= "-------------------------------------------------------------\n";
return $template;
}
sub GetSOPPath
{
my ($nLdsType, $nCoreType) = @_;
my $strPath = "./YYY/custom/system/Template/XXX/InputSectionRule.txt";
if($nLdsType == MAIN)
{
$strPath =~ s/XXX/lds_config/;
}
elsif($nLdsType == BL)
{
$strPath =~ s/XXX/BL_lds_config/;
}
elsif($nLdsType == EXT_BL)
{
$strPath = ~s/XXX/EXT_BL_lds_config/;
}
if($nCoreType == PCORE_TYPE)
{
$strPath =~ s/YYY/pcore/;
}
elsif($nCoreType == L1CORE_TYPE)
{
$strPath =~ s/YYY/l1core/;
}
$strPath = "./custom/system/Template/lds_config/InputSectionRule.txt";
return $strPath;
}
#****************************************************************************
# subroutine: Get_Template_Caution
# return: Template shown in log file to tell folks the risks
#****************************************************************************
sub Get_Template_Caution
{
my $template = <<"__TEMPLATE";
=====================================================================
[!!Caution!!]
Some functions, variables or assembly codes
in the following object list are wrapped around invalid sections,
which may cause bring-up failed due to region init not handling invalid regions.
Please fix it with Error Handling SOP as below.
__TEMPLATE
return $template;
}