imgtools/romtools/rombuild/r_areaset.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * Area-related classes implementation
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 #include "r_areaset.h"
       
    21 #include "r_global.h"
       
    22 #include "r_rom.h"
       
    23 
       
    24 extern TBool gGenDepGraph;
       
    25 extern char* gDepInfoFile;
       
    26 
       
    27 using namespace std;
       
    28 
       
    29 ////////////////////////////////////////////////////////////////////////
       
    30 
       
    31 Area::Area(const char* aName, TLinAddr aDestBaseAddr, TUint aMaxSize, Area* aNext)
       
    32 	: iFirstPagedCode(0),
       
    33 	  iName(strdup(aName)),
       
    34 	  iDestBaseAddr(aDestBaseAddr),
       
    35 	  iSrcBaseAddr(0),
       
    36 	  iSrcLimitAddr(0),
       
    37 	  iMaxSize(aMaxSize),
       
    38 	  iIsDefault(strcmp(aName, AreaSet::KDefaultAreaName) == 0),
       
    39 	  iFiles(0),
       
    40 	  iNextFilePtrPtr(&iFiles),
       
    41 	  iNextArea(aNext)
       
    42 	  
       
    43 	{
       
    44 	}
       
    45 
       
    46 
       
    47 Area::~Area()
       
    48 	{
       
    49 	ReleaseAllFiles();
       
    50 	free(const_cast<char*>(iName));	// allocated with strdup()
       
    51 	}
       
    52 
       
    53 
       
    54 /**
       
    55  Increase the size of the area.
       
    56 
       
    57  The reallocation must not exceed the area maximum size.
       
    58 
       
    59  @param aSrcLimitAddr New source top address
       
    60 
       
    61  @param aOverflow Number of overflow bytes if failure.
       
    62 
       
    63  @return success indication
       
    64 */
       
    65 
       
    66 TBool Area::ExtendSrcLimitAddr(TLinAddr aSrcLimitAddr, TUint& aOverflow)
       
    67 	{
       
    68 	// must have been set before
       
    69 	assert(iSrcBaseAddr != 0);
       
    70 	// can only allocate more
       
    71 	assert(aSrcLimitAddr > iSrcBaseAddr);
       
    72 
       
    73 	if (aSrcLimitAddr-iSrcBaseAddr > iMaxSize)
       
    74 		{
       
    75 		aOverflow = aSrcLimitAddr-iSrcBaseAddr-iMaxSize;
       
    76 		return EFalse;
       
    77 		}
       
    78 
       
    79 	iSrcLimitAddr = aSrcLimitAddr;
       
    80 	return ETrue;
       
    81 	}
       
    82 
       
    83 
       
    84 /**
       
    85  Add a file at end of the list of files contained in this area.
       
    86 
       
    87  @param aFile File to add.  Must be allocated on the heap.  Ownership
       
    88  is transfered from the caller to the callee.
       
    89 */
       
    90 
       
    91 void Area::AddFile(TRomBuilderEntry* aFile)
       
    92 	{
       
    93 	assert(aFile != 0);
       
    94 
       
    95 	*iNextFilePtrPtr = aFile;
       
    96 	iNextFilePtrPtr = &(aFile->iNextInArea);
       
    97 	}
       
    98 
       
    99 
       
   100 void Area::ReleaseAllFiles()
       
   101 	{
       
   102 	for (TRomBuilderEntry *next = 0, *current = iFiles;
       
   103 		 current != 0;
       
   104 		 current = next)
       
   105 		{
       
   106 		next = current->iNextInArea;
       
   107 		delete current;
       
   108 		}
       
   109 
       
   110 	iFiles = 0;
       
   111 	iNextFilePtrPtr = &iFiles;
       
   112 	}
       
   113 
       
   114 ////////////////////////////////////////////////////////////////////////
       
   115 
       
   116 void FilesInAreaIterator::GoToNext()
       
   117 	{
       
   118 	assert(iCurrentFile!=0);
       
   119 	iCurrentFile = iCurrentFile->iNextInArea;
       
   120 	}
       
   121 
       
   122 ////////////////////////////////////////////////////////////////////////
       
   123 
       
   124 const char AreaSet::KDefaultAreaName[] = "DEFAULT AREA";
       
   125 
       
   126 AreaSet::AreaSet()
       
   127 	: iNonDefaultAreas(0),
       
   128 	  iDefaultArea(0),
       
   129 	  iAreaCount(0)
       
   130 	{
       
   131 	}
       
   132 
       
   133 
       
   134 AreaSet::~AreaSet()
       
   135 	{
       
   136 	ReleaseAllAreas();
       
   137 	}
       
   138 
       
   139 
       
   140 inline TBool IsInRange(TLinAddr aAddr, TLinAddr aDestBaseAddr, TLinAddr aEndAddr)
       
   141 	{
       
   142 	return aDestBaseAddr <= aAddr && aAddr <= aEndAddr;
       
   143 	}
       
   144 
       
   145 
       
   146 /**
       
   147  Add a new area.
       
   148 
       
   149  Areas must have unique name, not overlap one another and not overflow
       
   150  the 32-bit address range.  
       
   151 
       
   152  @param aOverlappingArea On return ptr to name of overlapping area if
       
   153  any, 0 otherwise.
       
   154 
       
   155  @return EAdded if success, an error code otherwise.  
       
   156 */
       
   157 
       
   158 AreaSet::TAddResult AreaSet::AddArea(const char* aNewName,
       
   159 									 TLinAddr aNewDestBaseAddr,
       
   160 									 TUint aNewMaxSize,
       
   161 									 const char*& aOverlappingArea)
       
   162 	{
       
   163 	assert(aNewName != 0 && strlen(aNewName) > 0);
       
   164 	assert(aNewMaxSize > 0);
       
   165 
       
   166 	aOverlappingArea = 0;
       
   167 
       
   168 	//
       
   169 	// Checking new area validity
       
   170 	//
       
   171 
       
   172 	if (aNewDestBaseAddr+aNewMaxSize <= aNewDestBaseAddr)
       
   173 		return EOverflow;
       
   174 
       
   175 	TLinAddr newEndAddr = aNewDestBaseAddr+aNewMaxSize-1;
       
   176 
       
   177 	// iterate non default areas first, then the default one if any
       
   178 	Area* area=iNonDefaultAreas; 
       
   179 	while (area != 0)
       
   180 		{
       
   181 		if (strcmp(area->Name(), aNewName) == 0)
       
   182 			return EDuplicateName;
       
   183 
       
   184 		TLinAddr curDestBaseAddr = area->DestBaseAddr();
       
   185 		TLinAddr curEndAddr = area->DestBaseAddr()+area->MaxSize()-1;
       
   186 
       
   187 		if (IsInRange(newEndAddr, curDestBaseAddr, curEndAddr) ||
       
   188 			IsInRange(aNewDestBaseAddr, curDestBaseAddr, curEndAddr) ||
       
   189 			IsInRange(curDestBaseAddr, aNewDestBaseAddr, newEndAddr))
       
   190 			{
       
   191 			aOverlappingArea = area->Name();
       
   192 			return EOverlap;
       
   193 			}
       
   194 
       
   195 		if (area->iNextArea == 0 && area != iDefaultArea)
       
   196 			area = iDefaultArea;
       
   197 		else
       
   198 			area = area->iNextArea;
       
   199 		}
       
   200 	
       
   201 	//
       
   202 	// Adding new area
       
   203 	//
       
   204 
       
   205 	if (strcmp(KDefaultAreaName, aNewName) == 0)
       
   206 		iDefaultArea = new Area(aNewName, aNewDestBaseAddr, aNewMaxSize);
       
   207 	else
       
   208 		iNonDefaultAreas = new Area(aNewName, aNewDestBaseAddr, aNewMaxSize, iNonDefaultAreas);
       
   209 	++iAreaCount;
       
   210 
       
   211 	return EAdded;
       
   212 	}
       
   213 
       
   214 
       
   215 /**
       
   216  Remove every area added to the set.
       
   217 
       
   218  As a side-effect every file added to the areas is deleted.
       
   219 */
       
   220 
       
   221 void AreaSet::ReleaseAllAreas()
       
   222 	{
       
   223 	for (Area *next = 0, *current = iNonDefaultAreas; current != 0; current = next)
       
   224 		{
       
   225 		next = current->iNextArea;
       
   226 		delete current;
       
   227 		}
       
   228 
       
   229 	iNonDefaultAreas = 0;
       
   230 
       
   231 	delete iDefaultArea;
       
   232 	iDefaultArea = 0;
       
   233 	}
       
   234 
       
   235 
       
   236 /**
       
   237  Find an area from its name.
       
   238 
       
   239  @return A pointer to the area or 0 if the name is unknown.  The
       
   240  returned pointer becomes invalid when "this" is destructed.
       
   241 */
       
   242 
       
   243 Area* AreaSet::FindByName(const char* aName) const
       
   244 	{
       
   245 	assert(aName != 0 && strlen(aName) > 0);
       
   246 
       
   247 	if (iDefaultArea && strcmp(iDefaultArea->Name(), aName) == 0)
       
   248 		return iDefaultArea;
       
   249 
       
   250 	for (Area* area=iNonDefaultAreas; area != 0; area = area->iNextArea)
       
   251 		{
       
   252 		if (strcmp(area->Name(), aName) == 0)
       
   253 			return area;
       
   254 		}
       
   255 
       
   256 	return 0;
       
   257 	}
       
   258 
       
   259 
       
   260 ////////////////////////////////////////////////////////////////////////
       
   261 
       
   262 void NonDefaultAreasIterator::GoToNext()
       
   263 	{
       
   264 	assert(iCurrentArea!=0);
       
   265 	iCurrentArea = iCurrentArea->iNextArea;
       
   266 	}
       
   267 
       
   268 TInt Area::SortFilesForPagedRom()
       
   269 	{
       
   270 	Print(ELog,"Sorting files to paged/unpaged.\n");
       
   271 	TRomBuilderEntry* extention[2] = {0,0};
       
   272 	TRomBuilderEntry* unpaged[2] = {0,0};
       
   273 	TRomBuilderEntry* normal[2] = {0,0};
       
   274 	TRomBuilderEntry* current = iFiles;
       
   275 	while(current)
       
   276 		{
       
   277 		TRomBuilderEntry** list;
       
   278 		if((current->iRomImageFlags & (KRomImageFlagPrimary|KRomImageFlagVariant|KRomImageFlagExtension|KRomImageFlagDevice)) ||
       
   279 			current->HCRDataFile())
       
   280 			list = extention;
       
   281 		else if(current->iRomImageFlags&(KRomImageFlagCodeUnpaged))
       
   282 			list = unpaged;
       
   283 		else if(current->iResource && (current->iOverrideFlags&KOverrideCodeUnpaged) && gPagedRom)
       
   284 			list = unpaged;
       
   285 		else
       
   286 			list = normal;
       
   287 
       
   288 		if(list!=normal)
       
   289 			{
       
   290 			Print(ELog, "Unpaged file %s\n",current->iRomNode->BareName());
       
   291 			}
       
   292 
       
   293 		if(!list[0])
       
   294 			list[0] = current;
       
   295 		else
       
   296 			list[1]->iNextInArea = current;
       
   297 		list[1] = current;
       
   298 
       
   299 		current = current->iNext;
       
   300 		}
       
   301 
       
   302 	if(extention[1])
       
   303 		{
       
   304 		if(unpaged[0])
       
   305 			{
       
   306 			extention[1]->iNextInArea = unpaged[0];
       
   307 			unpaged[1]->iNextInArea = normal[0];
       
   308 			}
       
   309 		else
       
   310 			extention[1]->iNextInArea = normal[0];
       
   311 
       
   312 		if (normal[1])
       
   313 			normal[1]->iNextInArea = 0;
       
   314 
       
   315 		iFiles = extention[0];
       
   316 		}
       
   317 	else{
       
   318 		Print(EError,"No primary files.\n");
       
   319 		return KErrGeneral;
       
   320 	}
       
   321 
       
   322 	iFirstPagedCode = normal[0];
       
   323 	Print(ELog,"\n");
       
   324 	if(gGenDepGraph)
       
   325 		WriteDependenceGraph();
       
   326 	return KErrNone;
       
   327 	}
       
   328 
       
   329 
       
   330 void Area::WriteDependenceGraph()
       
   331 {
       
   332 	TDepInfoList::iterator infoIt;
       
   333 	TStringList::iterator strIt;
       
   334 	TDepInfoList myDepInfoList;
       
   335 	TRomBuilderEntry* e = iFirstPagedCode;
       
   336 	char buffer[255];
       
   337 	TInt count = 0;
       
   338 	TStringList nameList;
       
   339 	while(e)
       
   340 	{
       
   341 		DepInfo tmpDepInfo;
       
   342 		TRomNode* rn = e->iRomNode;
       
   343 		TInt ll = rn->FullNameLength();
       
   344 		char* mm = (char*) malloc(ll+1);
       
   345 		rn->GetFullName(mm);
       
   346 		sprintf(buffer, "f%d", count);
       
   347 		tmpDepInfo.portName = buffer;
       
   348 		tmpDepInfo.index = count;
       
   349 		myDepInfoList[mm] = tmpDepInfo;
       
   350 		nameList.push_back(mm);
       
   351 		free(mm);
       
   352 		e = e->iNextInArea;
       
   353 		count++;
       
   354 	}
       
   355 	e = iFirstPagedCode;
       
   356 	count = 0;
       
   357 	while(e)
       
   358 	{
       
   359 		TRomNode* rn = e->iRomNode;
       
   360 		TRomFile* rf = rn->iRomFile;
       
   361 		TInt j;
       
   362 		TStringList depFiles;
       
   363 		for(j=0; j < rf->iNumDeps; ++j)
       
   364 		{
       
   365 			TRomFile* f=rf->iDeps[j];
       
   366 			TRomBuilderEntry* start = iFiles;
       
   367 			while(start && start->iRomNode->iRomFile != f)
       
   368 				start = start->iNextInArea;
       
   369 			if(start && (start->iRomNode->iRomFile == f))
       
   370 			{
       
   371 				TRomNode* target = start->iRomNode;
       
   372 				TInt l = target->FullNameLength();
       
   373 				char* fname = (char *) malloc(l+1);
       
   374 				target->GetFullName(fname);
       
   375 				if(myDepInfoList.find(fname) != myDepInfoList.end())
       
   376 				{
       
   377 					depFiles.push_back(fname);
       
   378 					myDepInfoList[fname].beenDepended = ETrue;
       
   379 				}
       
   380 				free(fname);
       
   381 			}
       
   382 		}
       
   383 		if(depFiles.size() > 0)
       
   384 		{
       
   385 			myDepInfoList[nameList[count]].depFilesList=depFiles;
       
   386 			myDepInfoList[nameList[count]].dependOthers = ETrue;
       
   387 		}
       
   388 		count++;
       
   389 		e=e->iNextInArea;
       
   390 	}
       
   391 	ofstream os;
       
   392 	string filename(gDepInfoFile, strlen(gDepInfoFile) - 3);
       
   393 	filename = filename + "dot";
       
   394 	os.open(filename.c_str());
       
   395 	os << "digraph ROM {\n";
       
   396 	os << "rankdir = LR;\n";
       
   397 	os << "fontsize = 10;\n";
       
   398 	os << "fontname = \"Courier New\";\n";
       
   399 	os << "label = \"ROM DEPENDENCE GRAPH DOT FILE\";\n";
       
   400 	os << "node[shape = plaintext];\n";
       
   401 	os << "dependence[label=<<FONT FACE=\"Courier new\" POINT-SIZE=\"10pt\">\n";
       
   402 	os << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n";
       
   403 	//for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++)
       
   404 	for(strIt = nameList.begin(); strIt != nameList.end(); strIt++)
       
   405 	{
       
   406 		string tmp = *strIt;
       
   407 		string::iterator charIt;
       
   408 		for(charIt=tmp.begin(); charIt != tmp.end(); charIt++)
       
   409 		{
       
   410 			if(*charIt == '\\')
       
   411 				*charIt = '/';
       
   412 		}
       
   413 		if(myDepInfoList[*strIt].beenDepended && myDepInfoList[*strIt].dependOthers)
       
   414 		{
       
   415 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"yellow\">\n";
       
   416 			os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n";
       
   417 			os << "\t</TD></TR>\n";
       
   418 		}
       
   419 		else if(myDepInfoList[*strIt].beenDepended)
       
   420 		{
       
   421 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"gray\">\n";
       
   422 			os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n";
       
   423 			os << "\t</TD></TR>\n";
       
   424 		}
       
   425 		else if(myDepInfoList[*strIt].dependOthers)
       
   426 		{
       
   427 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"cyan\">\n";
       
   428 			os << "\t<FONT COLOR=\"blue\">" << tmp << "</FONT>\n";
       
   429 			os << "\t</TD></TR>\n";
       
   430 		}
       
   431 		else
       
   432 		{
       
   433 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\">";
       
   434 			os << tmp;
       
   435 			os << "</TD></TR>\n";
       
   436 		}
       
   437 	}
       
   438 	os << "</TABLE>\n";
       
   439 	os << "</FONT>>]\n";
       
   440 	TBool lastEdge = ETrue;
       
   441 	TBool first = ETrue;
       
   442 	for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++)
       
   443 	{
       
   444 		if(!infoIt->second.dependOthers)
       
   445 		{
       
   446 			continue;
       
   447 		}
       
   448 		for(strIt = infoIt->second.depFilesList.begin(); strIt != infoIt->second.depFilesList.end(); strIt++)
       
   449 		{
       
   450 			TBool tmpEdge = ETrue;
       
   451 			if(infoIt->second.index < myDepInfoList[*strIt].index)
       
   452 			{	
       
   453 				tmpEdge = EFalse;
       
   454 			}
       
   455 			if(first)
       
   456 			{
       
   457 				lastEdge = tmpEdge;
       
   458 				first = EFalse;
       
   459 				if(lastEdge)
       
   460 				{
       
   461 					os << "edge[color=forestgreen];\n";
       
   462 				}
       
   463 				else
       
   464 				{
       
   465 					os << "edge[color=red];\n";
       
   466 				}
       
   467 			}
       
   468 			else
       
   469 			{
       
   470 				if(lastEdge != tmpEdge)
       
   471 				{
       
   472 					lastEdge = tmpEdge;
       
   473 					if(lastEdge)
       
   474 					{
       
   475 						os << "edge[color=forestgreen];\n";
       
   476 					}
       
   477 					else
       
   478 					{
       
   479 						os << "edge[color=red];\n";
       
   480 					}
       
   481 				}
       
   482 			}
       
   483 			os << "dependence: " << infoIt->second.portName << " -> dependence: " << myDepInfoList[*strIt].portName << ";\n";
       
   484 		}
       
   485 	}
       
   486 	os << "}\n";
       
   487 	os.close();
       
   488 	filename = filename.substr(0, filename.size()-4);
       
   489 	filename = filename + ".backwarddep.dot";
       
   490 	os.open(filename.c_str());
       
   491 	os << "digraph ROM {\n";
       
   492 	os << "rankdir = LR;\n";
       
   493 	os << "fontsize = 10;\n";
       
   494 	os << "fontname = \"Courier New\";\n";
       
   495 	os << "label = \"ROM FORWARD DEPENDENCE GRAPH DOT FILE\";\n";
       
   496 	os << "node[shape = plaintext];\n";
       
   497 	os << "dependence[label=<<FONT FACE=\"Courier new\" POINT-SIZE=\"10pt\">\n";
       
   498 	os << "<TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLSPACING=\"0\">\n";
       
   499 	//for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++)
       
   500 	for(strIt = nameList.begin(); strIt != nameList.end(); strIt++)
       
   501 	{
       
   502 		string tmp = *strIt;
       
   503 		string::iterator charIt;
       
   504 		for(charIt=tmp.begin(); charIt != tmp.end(); charIt++)
       
   505 		{
       
   506 			if(*charIt == '\\')
       
   507 				*charIt = '/';
       
   508 		}
       
   509 		if(myDepInfoList[*strIt].beenDepended && myDepInfoList[*strIt].dependOthers)
       
   510 		{
       
   511 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"yellow\">\n";
       
   512 			os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n";
       
   513 			os << "\t</TD></TR>\n";
       
   514 		}
       
   515 		else if(myDepInfoList[*strIt].beenDepended)
       
   516 		{
       
   517 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"gray\">\n";
       
   518 			os << "\t<FONT COLOR=\"red\">" << tmp << "</FONT>\n";
       
   519 			os << "\t</TD></TR>\n";
       
   520 		}
       
   521 		else if(myDepInfoList[*strIt].dependOthers)
       
   522 		{
       
   523 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\" BGCOLOR=\"cyan\">\n";
       
   524 			os << "\t<FONT COLOR=\"blue\">" << tmp << "</FONT>\n";
       
   525 			os << "\t</TD></TR>\n";
       
   526 		}
       
   527 		else
       
   528 		{
       
   529 			os << "\t<TR><TD PORT=\"" << myDepInfoList[*strIt].portName << "\" ALIGN=\"LEFT\">";
       
   530 			os << tmp;
       
   531 			os << "</TD></TR>\n";
       
   532 		}
       
   533 	}
       
   534 	os << "</TABLE>\n";
       
   535 	os << "</FONT>>]\n";
       
   536 	os << "edge[color=red];\n";
       
   537 	for(infoIt = myDepInfoList.begin(); infoIt != myDepInfoList.end(); infoIt++)
       
   538 	{
       
   539 		if(!infoIt->second.dependOthers)
       
   540 		{
       
   541 			continue;
       
   542 		}
       
   543 		for(strIt = infoIt->second.depFilesList.begin(); strIt != infoIt->second.depFilesList.end(); strIt++)
       
   544 		{
       
   545 			if(infoIt->second.index < myDepInfoList[*strIt].index)
       
   546 			{	
       
   547 				os << "dependence: " << infoIt->second.portName << " -> dependence: " << myDepInfoList[*strIt].portName << ";\n";
       
   548 			}
       
   549 		}
       
   550 	}
       
   551 	os << "}\n";
       
   552 	os.close();
       
   553 }
       
   554