imgtools/romtools/rombuild/r_build.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 1995-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 *
       
    16 */
       
    17 
       
    18 
       
    19 #define __REFERENCE_CAPABILITY_NAMES__
       
    20 #include <stdlib.h>
       
    21 #include <string.h>
       
    22 #include <ctype.h>
       
    23 #include <e32std.h>
       
    24 #include <e32std_private.h>
       
    25 #include <e32rom.h>
       
    26 #include "u32std.h"
       
    27 #include <e32uid.h>
       
    28 #include <f32file.h>
       
    29 #include "h_utl.h"
       
    30 
       
    31 #define USE_IAT_FOR_IMPORTS (iOverrideFlags&KOverrideKeepIAT || (iHdr->iCpuIdentifier & 0x1000))
       
    32 
       
    33 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
    34 #include <iomanip>
       
    35 #else //!__MSVCDOTNET__
       
    36 #include <iomanip.h>
       
    37 #endif
       
    38 
       
    39 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
    40 #include <iomanip>
       
    41 #else //!__MSVCDOTNET__
       
    42 #include <iomanip.h>
       
    43 #endif
       
    44 
       
    45 #include "r_obey.h"
       
    46 #include "r_global.h"
       
    47 #include "r_dir.h"
       
    48 
       
    49 TInt NumRootDirs;
       
    50 
       
    51 inline TLinAddr ActualToRomAddress(TAny* anAddr)
       
    52 	{ return TLinAddr(anAddr)-TheRomMem+TheRomLinearAddress; }
       
    53 
       
    54 TBool THardwareVariant::MutuallyExclusive(THardwareVariant a) const
       
    55 	{
       
    56 	if (Layer()<=3 || a.Layer()<=3)
       
    57 		return EFalse;
       
    58 	if (Parent()==3 && a.Parent()==3)
       
    59 		return(Layer()!=a.Layer());
       
    60 	if (Parent()==3 && a.Parent()!=Layer())
       
    61 		return ETrue;
       
    62 	if (a.Parent()==3 && Parent()!=a.Layer())
       
    63 		return ETrue;
       
    64 	if (Layer()!=a.Layer())
       
    65 		return ETrue;
       
    66 	return((VMask()&a.VMask())==0);
       
    67 	}
       
    68 
       
    69 TBool THardwareVariant::IsVariant() const
       
    70 	{
       
    71 	if (Layer()<=3 || Parent()==3)
       
    72 		return EFalse;
       
    73 	TUint v=VMask();
       
    74 	TInt i;
       
    75 	for (i=0; i<16; i++)
       
    76 		{
       
    77 		if (v==TUint(1<<i))
       
    78 			return ETrue;
       
    79 		}
       
    80 	return EFalse;
       
    81 	}
       
    82 
       
    83 TInt THardwareVariant::Compare(THardwareVariant a) const
       
    84 	{
       
    85 	TUint l1=Layer();
       
    86 	TUint p1=Parent();
       
    87 	TUint v1=VMask();
       
    88 	TUint l2=a.Layer();
       
    89 	TUint p2=a.Parent();
       
    90 	TUint v2=a.VMask();
       
    91 
       
    92 	if (l1<=3)
       
    93 		{
       
    94 		if (l2<=3)
       
    95 			{
       
    96 			return EEqual;
       
    97 			}
       
    98 		return EGreater;
       
    99 		}
       
   100 	if (l2<=3)
       
   101 		return ELess;
       
   102 	if (p1==3)
       
   103 		{
       
   104 		if (p2==3)
       
   105 			{
       
   106 			if (l1==l2)
       
   107 				return EEqual;
       
   108 			return EUnordered;
       
   109 			}
       
   110 		if (p2==l1)
       
   111 			return EGreater;
       
   112 		return EUnordered;
       
   113 		}
       
   114 	if (p2==3)
       
   115 		{
       
   116 		if (p1==l2)
       
   117 			return ELess;
       
   118 		return EUnordered;
       
   119 		}
       
   120 	if (l1!=l2)
       
   121 		return EUnordered;
       
   122 	if ((v1&v2)==v1)
       
   123 		return ELess;
       
   124 	if ((v1&v2)==v2)
       
   125 		return EGreater;
       
   126 	return EUnordered;
       
   127 	}
       
   128 //
       
   129 TInt TRomNode::Count=0;
       
   130 TRomNode::TRomNode(const TText* aName, TRomBuilderEntry* aEntry)
       
   131 //
       
   132 // Constructor from TRomBuilderEntry, i.e. for new file or directory
       
   133 //
       
   134 	{
       
   135 	memset(this, 0, sizeof(TRomNode));
       
   136 	iAtt = (TUint8)KEntryAttReadOnly;
       
   137 	iName = (TText*)NormaliseFileName((const char*)aName);
       
   138 	iIdentifier=TRomNode::Count++;
       
   139 	iRomFile = new TRomFile;
       
   140 	if (aEntry)
       
   141 		{
       
   142 		iRomFile->iRbEntry = aEntry;
       
   143 		aEntry->SetRomNode(this);
       
   144 		iBareName = strdup(aEntry->iBareName);
       
   145 		iRomFile->iHwvd = aEntry->iHardwareVariant;
       
   146 		}
       
   147 	else
       
   148 		{
       
   149 		iRomFile->iDir = ETrue;
       
   150 		iAtt |= (TUint8)KEntryAttDir;
       
   151 		iBareName = strdup((const char*)iName);
       
   152 		iRomFile->iHwvd = KVariantIndependent;
       
   153 		}
       
   154 	TRACE(TROMNODE,Print(ELog, "TRomNode %d name %s bare %s att %02x romfile %08x\n", iIdentifier,
       
   155 			iName, iBareName, iAtt, iRomFile));
       
   156 	}
       
   157 
       
   158 TRomNode::TRomNode(const TText* aName, TRomNode* aNode)
       
   159 //
       
   160 // Constructor from TRomNode, i.e. for aliased file
       
   161 //
       
   162 	{
       
   163 	memset(this, 0, sizeof(TRomNode));
       
   164 	iAtt = aNode->iAtt;
       
   165 	iIdentifier=TRomNode::Count++;
       
   166 	iName = (TText*)NormaliseFileName((const char*)aName);
       
   167 	iHidden = aNode->iHidden;
       
   168 	iRomFile = aNode->iRomFile;
       
   169 	if (iRomFile)
       
   170 		{
       
   171 		iRomFile->Open();
       
   172 		}
       
   173 	TRACE(TROMNODE,Print(ELog, "TRomNode %d DUP name %s romfile %08x\n", iIdentifier, iName, iRomFile));
       
   174 	}
       
   175 
       
   176 TRomNode::TRomNode(const TRomNode& aNode)
       
   177 //
       
   178 // Copy constructor - only used in deep copy function
       
   179 //
       
   180 	{
       
   181 	memset(this, 0, sizeof(TRomNode));
       
   182 	iAtt = aNode.iAtt;
       
   183 	iIdentifier=TRomNode::Count++;
       
   184 	iName = (TText*)strdup((const char*)aNode.iName);
       
   185 	iBareName = strdup(aNode.iBareName);
       
   186 	iHidden = aNode.iHidden;
       
   187 	iRomFile = aNode.iRomFile;
       
   188 	if (iRomFile)
       
   189 		{
       
   190 		iRomFile->Open();
       
   191 		}
       
   192 	TRACE(TROMNODE,Print(ELog, "TRomNode %d COPY name %s bare %s att %02x romfile %08x\n", iIdentifier,
       
   193 			iName, iBareName, iAtt, iRomFile));
       
   194 	}
       
   195 
       
   196 TRomNode::~TRomNode()
       
   197 	{
       
   198 	free(iName);
       
   199 	free(iBareName);
       
   200 	if (iRomFile)
       
   201 		iRomFile->Close();
       
   202 	}
       
   203 
       
   204 TRomNode* TRomNode::FindInDirectory(const TText* aName)
       
   205 //
       
   206 // Check if the TRomNode for aName exists in aDir, and if so, return it.
       
   207 //
       
   208 	{
       
   209 
       
   210 	TRomNode *entry=iChild; // first subdirectory or file
       
   211 	while (entry)
       
   212 		{
       
   213 		if (!entry->iHidden && (stricmp((const char *)aName, (const char *)entry->iName))==0) 
       
   214 			return entry;
       
   215 		else
       
   216 			entry=entry->iSibling;
       
   217 		}
       
   218 	return 0;
       
   219 	}
       
   220 
       
   221 TRomNode* TRomNode::FindInDirectory(const TText* aName, THardwareVariant aVariant, TBool aPatchDataFlag)
       
   222 //
       
   223 // Check for a file with same name and a compatible hardware variant
       
   224 //
       
   225 	{
       
   226 
       
   227 	TRomNode *entry=iChild; // first subdirectory or file
       
   228 	while (entry)
       
   229 		{
       
   230 		if (((!entry->iHidden)||aPatchDataFlag) && entry->iRomFile && (stricmp((const char *)aName, (const char *)entry->iName))==0) 
       
   231 			{
       
   232 			if (!aVariant.MutuallyExclusive(entry->HardwareVariant()))
       
   233 				return entry;
       
   234 			}
       
   235 		entry=entry->iSibling;
       
   236 		}
       
   237 	return 0;
       
   238 	}
       
   239 
       
   240 void TRomNode::AddFile(TRomNode* aChild)
       
   241 	{
       
   242 	if (!(iAtt & KEntryAttDir))
       
   243 		{
       
   244 		Print(EError, "Adding subdirectory to a file!!!\n");
       
   245 		return;
       
   246 		}
       
   247 	Add(aChild);
       
   248 	}
       
   249 
       
   250 TRomNode* TRomNode::NewSubDir(const TText* aName)
       
   251 	{
       
   252 	if (!(iAtt & KEntryAttDir))
       
   253 		{
       
   254 		Print(EError, "Adding subdirectory to a file!!!\n");
       
   255 		return 0;
       
   256 		}
       
   257 
       
   258 	TRomNode* node = new TRomNode(aName);
       
   259 	if (node==0)
       
   260 		{
       
   261 		Print(EError, "TRomNode::NewNode: Out of memory\n");
       
   262 		return 0;
       
   263 		}
       
   264 	Add(node);
       
   265 	return node;
       
   266 	}
       
   267 
       
   268 void TRomNode::Add(TRomNode* aChild)
       
   269 	{
       
   270 	if (iChild) // this node is a non-empty directory
       
   271 		{
       
   272 		TRomNode* dir = iChild; // find where to link in the new node
       
   273 		while (dir->iSibling)
       
   274 			dir = dir->iSibling;
       
   275 		dir->iSibling = aChild;
       
   276 		}
       
   277 	else
       
   278 		iChild = aChild; // else just set it up as the child of the dir
       
   279 	aChild->iSibling = 0;
       
   280 	aChild->iParent = this;
       
   281 	}
       
   282 
       
   283 void TRomNode::Remove(TRomNode* aChild)
       
   284 	{
       
   285 	if (iChild==0)
       
   286 		{
       
   287 		Print(EError, "Removing file from a file!!!\n");
       
   288 		return;
       
   289 		}
       
   290 	if (iChild==aChild) // first child in this directory
       
   291 		{
       
   292 		iChild = aChild->iSibling;
       
   293 		aChild->iSibling = 0;
       
   294 		aChild->iParent = 0;
       
   295 		return;
       
   296 		}
       
   297 	TRomNode* prev = iChild;
       
   298 	while (prev->iSibling && prev->iSibling != aChild)
       
   299 		prev = prev->iSibling;
       
   300 	if (prev==0)
       
   301 		{
       
   302 		Print(EError, "Attempting to remove file not in this directory!!!\n");
       
   303 		return;
       
   304 		}
       
   305 	prev->iSibling = aChild->iSibling;
       
   306 	aChild->iSibling = 0;
       
   307 	aChild->iParent = 0;
       
   308 	}
       
   309 
       
   310 void TRomNode::CountDirectory(TInt& aFileCount, TInt& aDirCount)
       
   311 	{
       
   312 	TRomNode *current=iChild;
       
   313 	while(current)
       
   314 		{
       
   315 		if (current->iChild)
       
   316 			aDirCount++;
       
   317 		else if (!current->iHidden)
       
   318 			aFileCount++;
       
   319 		current=current->iSibling;
       
   320 		}
       
   321 	}
       
   322 
       
   323 /**
       
   324  * Walk the contents of the directory, accumulating the
       
   325  * files as FileEntry objects in the specified RomFileStructure
       
   326  * and recursively handling the sub-directories
       
   327  *
       
   328  * TRomNode::ProcessDirectory is a pair with
       
   329  * RomFileStructure::ProcessDirectory
       
   330  */
       
   331 int TRomNode::ProcessDirectory(RomFileStructure* aRFS)
       
   332 	{
       
   333 	TInt r=KErrNone;
       
   334 	TRomNode *current=iChild;
       
   335 	while(current)
       
   336 		{
       
   337 		if (current->iAtt & (TUint8)KEntryAttDir)
       
   338 			{
       
   339 			r=aRFS->ProcessDirectory(current);
       
   340 			if (r!=KErrNone)
       
   341 				return r;
       
   342 			}
       
   343 		else if (!current->iHidden)
       
   344 			{
       
   345 			FileEntry *pE=FileEntry::New(current);
       
   346 			if (!pE)
       
   347 				return KErrNoMemory;
       
   348 			r=aRFS->Add(*pE);
       
   349 			if (r==KErrOverflow)
       
   350 				return r;
       
   351 			}
       
   352 		current=current->iSibling;
       
   353 		}
       
   354 	return r;
       
   355 	}
       
   356 
       
   357 void TRomNode::AddExecutableFile(TRomNode*& aLast, TRomNode* aNode)
       
   358 	{
       
   359 	aLast->iNextExecutable = aNode;
       
   360 	aLast = aNode;
       
   361 	aNode->iAtt |= KEntryAttXIP;
       
   362 	}
       
   363 
       
   364 char* TRomNode::BareName() const
       
   365 	{
       
   366 	return iBareName;
       
   367 	}
       
   368 
       
   369 TUint32 TRomNode::Uid3() const
       
   370 	{
       
   371 	return iRomFile->Uid3();
       
   372 	}
       
   373 
       
   374 TUint32 TRomNode::ModuleVersion() const
       
   375 	{
       
   376 	return iRomFile->ModuleVersion();
       
   377 	}
       
   378 
       
   379 THardwareVariant TRomNode::HardwareVariant() const
       
   380 	{
       
   381 	return iRomFile->HardwareVariant();
       
   382 	}
       
   383 
       
   384 TUint32 TRomNode::ABI() const
       
   385 	{
       
   386 	return iRomFile->ABI();
       
   387 	}
       
   388 
       
   389 TUint32 TRomFile::Uid3() const
       
   390 	{
       
   391 	assert(!iDir);
       
   392 	if (iRbEntry)
       
   393 	{
       
   394 		if(iRbEntry->iHdr)
       
   395 			return iRbEntry->iHdr->iUid3;
       
   396 	}
       
   397 	return RomImgHdr()->iUid3;
       
   398 	}
       
   399 
       
   400 TUint32 TRomFile::ModuleVersion() const
       
   401 	{
       
   402 	assert(!iDir);
       
   403 	if (iRbEntry)
       
   404 	{
       
   405 		if(iRbEntry->iHdr)
       
   406 			return iRbEntry->iHdr->ModuleVersion();
       
   407 	}
       
   408 	return RomImgHdr()->iModuleVersion;
       
   409 	}
       
   410 
       
   411 THardwareVariant TRomFile::HardwareVariant() const
       
   412 	{
       
   413 	return iHwvd;
       
   414 	}
       
   415 
       
   416 TUint32 TRomFile::ABI() const
       
   417 	{
       
   418 	assert(!iDir);
       
   419 	if (iRbEntry)
       
   420 	{
       
   421 		if(iRbEntry->iHdr)
       
   422 			return iRbEntry->iHdr->ABI();
       
   423 	}
       
   424 	return RomImgHdr()->iFlags & KRomImageABIMask;
       
   425 	}
       
   426 
       
   427 TInt TRomFile::ExportDirCount() const
       
   428 	{
       
   429 	assert(!iDir);
       
   430 	if (iRbEntry)
       
   431 	{
       
   432 		if(iRbEntry->iHdr)
       
   433 			return iRbEntry->iHdr->iExportDirCount;
       
   434 	}
       
   435 	return RomImgHdr()->iExportDirCount;
       
   436 	}
       
   437 
       
   438 TUint32 TRomFile::RomImageFlags() const
       
   439 	{
       
   440 	assert(!iDir);
       
   441 	if (iRbEntry)
       
   442 		{
       
   443 		if(iRbEntry->iHdr)
       
   444 		{
       
   445 		const TUint KRomFlagMask = KImageDll | KImageNoCallEntryPoint | KImageFixedAddressExe | KImageNmdExpData;
       
   446 		TUint romflags = iRbEntry->iHdr->iFlags & KRomFlagMask;
       
   447 		return iRbEntry->iRomImageFlags | romflags;
       
   448 		}
       
   449 		}
       
   450 	return RomImgHdr()->iFlags;
       
   451 	}
       
   452 
       
   453 TLinAddr TRomFile::DataBssLinearBase() const
       
   454 	{
       
   455 	assert(!iDir);
       
   456 	if (iRbEntry)
       
   457 		return iRbEntry->iDataBssLinearBase;
       
   458 	return RomImgHdr()->iDataBssLinearBase;
       
   459 	}
       
   460 
       
   461 const SSecurityInfo& TRomFile::SecurityInfo() const
       
   462 	{
       
   463 	assert(!iDir);
       
   464 	if (iRbEntry)
       
   465 		return iRbEntry->iS;
       
   466 	return RomImgHdr()->iS;
       
   467 	}
       
   468 
       
   469 TInt TRomNode::FullNameLength(TBool aIgnoreHiddenAttrib) const
       
   470 	{
       
   471 	TInt l = 0;
       
   472 	// aIgnoreHiddenAttrib is used to find the complete file name length as
       
   473 	// in ROM of a hidden file.
       
   474 	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
       
   475 		l = iParent->FullNameLength() + 1;
       
   476 	l += strlen((const char*)iName);
       
   477 	return l;
       
   478 	}
       
   479 
       
   480 TInt TRomNode::GetFullName(char* aBuf, TBool aIgnoreHiddenAttrib) const
       
   481 	{
       
   482 	TInt l = 0;
       
   483 	TInt nl = strlen((const char*)iName);
       
   484 	// aIgnoreHiddenAttrib is used to find the complete file name as in ROM of a hidden file.
       
   485 	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
       
   486 		l = iParent->GetFullName(aBuf);
       
   487 	char* b = aBuf + l;
       
   488 	if (l)
       
   489 		*b++ = '\\', ++l;
       
   490 	memcpy(b, iName, nl);
       
   491 	b += nl;
       
   492 	*b = 0;
       
   493 	l += nl;
       
   494 	return l;
       
   495 	}
       
   496 
       
   497 TInt CompareCapabilities(const SCapabilitySet& aSubCaps, const SCapabilitySet& aSuperCaps, const char* aSubName, const char* aSuperName)
       
   498 //
       
   499 //	Check that a aSubCaps are a subset of aSuperCaps
       
   500 //
       
   501 	{
       
   502 	if ((!gPlatSecEnforcement)&&(!gPlatSecDiagnostics))
       
   503 		return KErrNone;
       
   504 	TInt i;
       
   505 	TUint32 c = 0;
       
   506 	for (i=0; i<SCapabilitySet::ENCapW; ++i)
       
   507 		c |= (aSubCaps[i] &~ aSuperCaps[i]);
       
   508 	TInt r = c ? KErrPermissionDenied : KErrNone;
       
   509 	if (r && aSubName && aSuperName)
       
   510 		{
       
   511 		TPrintType printType;
       
   512 		if(gPlatSecEnforcement)
       
   513 			printType = EError;
       
   514 		else
       
   515 			{
       
   516 			printType = EWarning;
       
   517 			r = KErrNone;
       
   518 			}
       
   519 		char* buf = (char*)malloc(2);
       
   520 		if(!buf)
       
   521 			return KErrNoMemory;
       
   522 		TInt len = 0;
       
   523 		for(i=0; i<ECapability_Limit; i++)
       
   524 			{
       
   525 			if( (aSubCaps[i>>5] &~ aSuperCaps[i>>5]) & (1<<(i&31)) )
       
   526 				{
       
   527 				// append capability name to buf
       
   528 				const char* name = CapabilityNames[i];
       
   529 				if(!name)
       
   530 					continue;
       
   531 				if(len)
       
   532 					{
       
   533 					buf[len++] = ' ';
       
   534 					}
       
   535 				int nameLen=strlen(name);
       
   536 				buf = (char*)realloc(buf,len+nameLen+2);
       
   537 				if(!buf)
       
   538 					return KErrNoMemory;
       
   539 				memcpy(buf+len,CapabilityNames[i],nameLen);
       
   540 				len += nameLen;
       
   541 				}
       
   542 			}
       
   543 		buf[len]=0;
       
   544 		Print(printType, "*PlatSec* %s - Capability check failed. Can't load %s because it links to %s which has the following capabilities missing: %s\n",gPlatSecEnforcement?"ERROR":"WARNING",aSubName, aSuperName, buf);
       
   545 		free(buf);
       
   546 		}
       
   547 	return r;
       
   548 	}
       
   549 
       
   550 TDllFindInfo::TDllFindInfo(const char* aImportName, const TRomBuilderEntry* aEntry)
       
   551 	{
       
   552 	TUint32 flags;
       
   553 	iBareName = SplitFileName(aImportName, iUid3, iModuleVersion, flags);
       
   554 	assert(iBareName != 0);
       
   555 	iHwVariant = aEntry->iHardwareVariant.ReturnVariant(); 
       
   556 	}
       
   557 
       
   558 TDllFindInfo::~TDllFindInfo()
       
   559 	{
       
   560 	free((void*)iBareName);
       
   561 	}
       
   562 
       
   563 // Generate name as follows:
       
   564 // PC filename (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
       
   565 TModuleName::TModuleName(const TRomBuilderEntry* a)
       
   566 	{
       
   567 	TInt l = strlen(a->iFileName) + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
       
   568 	iName = (char*)malloc(l + 1);
       
   569 	assert(iName != 0);
       
   570 	sprintf(iName, "%s (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", a->iFileName, a->iHdr->iUid3,
       
   571 		a->iHardwareVariant.ReturnVariant(), a->iHdr->ModuleVersion()>>16, a->iHdr->ModuleVersion()&0x0000ffffu);
       
   572 	}
       
   573 
       
   574 // Generate name as follows:
       
   575 // Bare name (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
       
   576 TModuleName::TModuleName(const TDllFindInfo& a)
       
   577 	{
       
   578 	TInt l = strlen(a.iBareName) + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
       
   579 	iName = (char*)malloc(l + 1);
       
   580 	assert(iName != 0);
       
   581 	sprintf(iName, "%s (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", a.iBareName, a.iUid3,
       
   582 		a.iHwVariant, a.iModuleVersion>>16, a.iModuleVersion&0x0000ffffu);
       
   583 	}
       
   584 
       
   585 // Generate name as follows:
       
   586 // Name (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
       
   587 TModuleName::TModuleName(const TRomNode& a)
       
   588 	{
       
   589 	TBool xip = (a.iAtt & KEntryAttXIP);
       
   590 	TUint32 uid3 = xip ? a.Uid3() : 0;
       
   591 	TUint32 hwvd = (TUint)a.HardwareVariant();
       
   592 	TUint32 ver = xip ? a.ModuleVersion() : 0;
       
   593 	TInt l = a.FullNameLength() + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
       
   594 	iName = (char*)malloc(l + 1);
       
   595 	assert(iName != 0);
       
   596 	char* b = iName + a.GetFullName(iName);
       
   597 	sprintf(b, " (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", uid3, hwvd, ver>>16, ver&0x0000ffffu);
       
   598 	}
       
   599 
       
   600 TModuleName::TModuleName(const TRomFile& a, const TRomNode* aRootDir)
       
   601 	{
       
   602 	iName = 0;
       
   603 	if (a.iRbEntry)
       
   604 		{
       
   605 		new (this) TModuleName(a.iRbEntry);
       
   606 		return;
       
   607 		}
       
   608 	TRomNode* x = aRootDir->iNextExecutable;
       
   609 	for(; x; x=x->iNextExecutable)
       
   610 		{
       
   611 		if (x->iRomFile == &a)
       
   612 			{
       
   613 			new (this) TModuleName(*x);
       
   614 			return;
       
   615 			}
       
   616 		}
       
   617 	}
       
   618 
       
   619 TModuleName::~TModuleName()
       
   620 	{
       
   621 	free(iName);
       
   622 	}
       
   623 
       
   624 
       
   625 /**
       
   626  * TRomNode::FindImageFileByName is always called on the root TRomNode, so
       
   627  * it doesn't consider the current TRomNode, just the linked items in the
       
   628  * iNextExecutable list.
       
   629  */
       
   630 TRomNode* TRomNode::FindImageFileByName(const TDllFindInfo& aInfo, TBool aPrintDiag, TBool& aFallBack)
       
   631 	{
       
   632 	TUint r_major = aInfo.iModuleVersion >> 16;
       
   633 	TUint r_minor = aInfo.iModuleVersion & 0x0000ffffu;
       
   634 	TRomNode* fallback = NULL;
       
   635 	aFallBack = EFalse;
       
   636 	for (TRomNode* x=iNextExecutable; x!=0; x=x->iNextExecutable)
       
   637 		{
       
   638 		if (stricmp(x->BareName(), aInfo.iBareName))
       
   639 			continue;	// name doesn't match
       
   640 		if (aPrintDiag)
       
   641 			Print(ELog, "Candidate: %s ", (const char*)TModuleName(*x) );
       
   642 		if ( !(THardwareVariant(aInfo.iHwVariant) <= x->HardwareVariant()) )
       
   643 			{
       
   644 			if (aPrintDiag)
       
   645 				Print(ELog, "HWVD mismatch - requested %08x\n", aInfo.iHwVariant);
       
   646 			continue;
       
   647 			}
       
   648 		if (aInfo.iUid3 && (aInfo.iUid3 != x->Uid3()))
       
   649 			{
       
   650 			if (aPrintDiag)
       
   651 				Print(ELog, "UID3 mismatch - requested %08x\n", aInfo.iUid3);
       
   652 			continue;
       
   653 			}
       
   654 		TUint x_major = x->ModuleVersion() >> 16;
       
   655 		TUint x_minor = x->ModuleVersion() & 0x0000ffffu;
       
   656 		if ( x->ModuleVersion() == 0x00010000 && aInfo.iModuleVersion == 0 )
       
   657 			{
       
   658 			// allow requested version 0.0 to link to 1.0 with a warning
       
   659 			fallback = x;
       
   660 			}
       
   661 		if ( x_major != r_major )
       
   662 			{
       
   663 			if (aPrintDiag)
       
   664 				Print(ELog, "Major version mismatch - requested %d\n", r_major);
       
   665 			continue;
       
   666 			}
       
   667 		if ( x_minor < r_minor )
       
   668 			{
       
   669 			if (aPrintDiag)
       
   670 				Print(ELog, "??? Minor version mismatch - requested %d\n", r_minor);
       
   671 			continue;
       
   672 			}
       
   673 		if (aPrintDiag)
       
   674 			Print(ELog, "OK\n");
       
   675 		return x;
       
   676 		}
       
   677 	if (fallback)
       
   678 		{
       
   679 		aFallBack = ETrue;
       
   680 		return fallback;
       
   681 		}
       
   682 	return 0;
       
   683 	}
       
   684 
       
   685 TInt TRomNode::CheckForVersionConflicts(const TRomBuilderEntry* a)
       
   686 	{
       
   687 	TUint r_major = a->iHdr->ModuleVersion() >> 16;
       
   688 	TUint r_minor = a->iHdr->ModuleVersion() & 0x0000ffffu;
       
   689 	TInt errors = 0;
       
   690 	for (TRomNode* x=iNextExecutable; x!=0; x=x->iNextExecutable)
       
   691 		{
       
   692 		if (x->iRomFile->iRbEntry == a)
       
   693 			continue;	// don't compare a with itself
       
   694 		if (stricmp(x->BareName(), a->iBareName))
       
   695 			continue;	// name doesn't match
       
   696 		if ( a->iHardwareVariant.MutuallyExclusive(x->HardwareVariant()) )
       
   697 			continue;	// HWVDs are mutually exclusive
       
   698 		if ( a->iHdr->iUid3 && x->Uid3() && (a->iHdr->iUid3 != x->Uid3()) )
       
   699 			continue;	// UID3's don't match
       
   700 		TUint x_major = x->ModuleVersion() >> 16;
       
   701 		TUint x_minor = x->ModuleVersion() & 0x0000ffffu;
       
   702 		if (x_major == r_major && x_minor != r_minor)	// allow two copies of same file
       
   703 			{
       
   704 			Print(EError, "Version Conflict %s with %s\n", (const char*)TModuleName(a), (const char*)TModuleName(*x) );
       
   705 			++errors;
       
   706 			}
       
   707 		}
       
   708 	return errors;
       
   709 	}
       
   710 
       
   711 TInt E32Rom::WriteHeadersToRom(char *anAddr)
       
   712 //
       
   713 // Follow the TRomBuilderEntry tree, writing TRomEntry headers to the rom.
       
   714 //
       
   715 	{
       
   716 	TRACE(TTIMING,Print(EAlways,"0\n"));
       
   717 	TRACE(TDIR,Print(EAlways,"WriteHeadersToRom()\n"));
       
   718 	char* start=anAddr;
       
   719 	TRomRootDirectoryList* dirPointers=(TRomRootDirectoryList*)anAddr;
       
   720 	anAddr+=NumberOfVariants*sizeof(TRootDirInfo)+sizeof(TInt);
       
   721 	RomFileStructure* pS=RomFileStructure::New(NumberOfVariants);
       
   722 	if (!pS)
       
   723 		Print(EError,"Error creating RomFileStructure\n");
       
   724 	TInt r=pS->ProcessDirectory(iObey->iRootDirectory);
       
   725 	if (r!=KErrNone)
       
   726 		Print(EError,"Error %d processing directory tree\n",r);
       
   727 	TInt c=pS->Count();
       
   728 	NumRootDirs=c;
       
   729 	if (c!=NumberOfVariants)
       
   730 		Print(EError,"Error processing directory tree NR=%d NV=%d\n",c,NumberOfVariants);
       
   731 	dirPointers->iNumRootDirs=c;
       
   732 	TInt i;
       
   733 	TRACE(TDIR,Print(EAlways,"Count=%d\n",c));
       
   734 	TRACE(TDIR,pS->DebugPrint());
       
   735 	for(i=0; i<c; i++)
       
   736 		{
       
   737 		DirEntry* pD=(DirEntry*)&(*pS)[i];
       
   738 		TRomDir* pR=pD->CreateRomEntries(anAddr);
       
   739 		dirPointers->iRootDir[i].iHardwareVariant=TUint(pD->Variants().Lookup());
       
   740 		dirPointers->iRootDir[i].iAddressLin=ActualToRomAddress(pR);
       
   741 		}
       
   742 	TRACE(TDIR,Print(EAlways,"Beginning final cleanup\n"));
       
   743 	delete pS;
       
   744 	TRACE(TTIMING,Print(EAlways,"1\n"));
       
   745 	return anAddr-start;
       
   746 	}
       
   747 
       
   748  void TRomNode::Destroy()
       
   749 //
       
   750 // Follow the TRomNode tree, destroying it
       
   751 //
       
   752 	{
       
   753 
       
   754  	TRomNode *current = this; // root has no siblings
       
   755 	while (current)
       
   756 		{
       
   757 		if (current->iChild)
       
   758 			current->iChild->Destroy();
       
   759 		TRomNode* prev=current;
       
   760 		current=current->iSibling;
       
   761 		delete prev;
       
   762 		}
       
   763  	}
       
   764 
       
   765 
       
   766 TInt TRomNode::SetAtt(TText *anAttWord)
       
   767 //
       
   768 // Set the file attribute byte from the letters passed
       
   769 //
       
   770 	{
       
   771 	iAtt=0;
       
   772 	if (anAttWord==0 || anAttWord[0]=='\0')
       
   773 		return Print(EError, "Missing argument for keyword 'attrib'.\n");
       
   774 	for (TText *letter=anAttWord;*letter!=0;letter++)
       
   775 		{
       
   776 		switch (*letter)
       
   777 			{
       
   778 		case 'R':
       
   779 		case 'w':
       
   780 			iAtt |= KEntryAttReadOnly;
       
   781 			break;
       
   782 		case 'r':
       
   783 		case 'W':
       
   784 			iAtt &= ~KEntryAttReadOnly;
       
   785 			break;
       
   786 		case 'H':
       
   787 			iAtt |= KEntryAttHidden;
       
   788 			break;
       
   789 		case 'h':
       
   790 			iAtt &= ~KEntryAttHidden;
       
   791 			break;
       
   792 		case 'S':
       
   793 			iAtt |= KEntryAttSystem;
       
   794 			break;
       
   795 		case 's':
       
   796 			iAtt &= ~KEntryAttSystem;
       
   797 			break;
       
   798 		default:
       
   799 			return Print(EError, "Unrecognised attrib - '%c'.\n", *letter);
       
   800 			break;
       
   801 			}
       
   802 		}
       
   803 	return KErrNone;
       
   804 	}
       
   805 
       
   806 TRomBuilderEntry::TRomBuilderEntry(const char *aFileName,TText *aName)
       
   807 //
       
   808 // Constructor
       
   809 //
       
   810 	:
       
   811 	E32ImageFile(),
       
   812 	iName(0),
       
   813 	iResource(EFalse), iNonXIP(EFalse), iPreferred(EFalse), iCompression(0), iPatched(EFalse),iArea(0),
       
   814 	iOverrideFlags(0),iCodeAlignment(0),iDataAlignment(0),iUid1(0), iUid2(0), iUid3(0),iBareName(0), 
       
   815 	iHardwareVariant(KVariantIndependent),iDataBssOffset(0xffffffff), 
       
   816 	iStackReserve(0),iIATRefs(0), iNext(0), iNextInArea(0), 
       
   817 	iRomImageFlags(0),iProcessName(0), iRomNode(NULL)
       
   818 	{
       
   819 	if (aFileName)
       
   820    		iFileName = NormaliseFileName((const char*)aFileName);
       
   821 	if (aName)
       
   822 		iName = (TText*)NormaliseFileName((const char*)aName);
       
   823 	}
       
   824 
       
   825 TRomBuilderEntry::~TRomBuilderEntry()
       
   826 //
       
   827 // Destructor
       
   828 //
       
   829 	{
       
   830 
       
   831 	free(iFileName);
       
   832 	iFileName = 0;
       
   833 	free(iName);
       
   834 	iName = 0;
       
   835 	delete[] iProcessName;
       
   836 	free(iBareName);
       
   837 	iBareName = 0;
       
   838 	delete[] iIATRefs;
       
   839 	}
       
   840 
       
   841 TInt isNumber(TText *aString)
       
   842 	{
       
   843 	if (aString==NULL)
       
   844 		return 0;
       
   845 	if (strlen((char *)aString)==0)
       
   846 		return 0;
       
   847 	return isdigit(aString[0]);
       
   848 	}
       
   849 
       
   850 TInt getNumber(TText *aStr)
       
   851 	{
       
   852 	TUint a;
       
   853 	#ifdef __TOOLS2__
       
   854 	istringstream val((char *)aStr);
       
   855 	#else
       
   856 	istrstream val((char *)aStr,strlen((char *)aStr));
       
   857 	#endif
       
   858 
       
   859 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
   860 	val >> setbase(0);
       
   861 #endif //__MSVCDOTNET__
       
   862 
       
   863 	val >> a;
       
   864 	return a;
       
   865 	}
       
   866 
       
   867 TInt TRomBuilderEntry::SetCodeAlignment(TText* aStr)
       
   868 	{
       
   869     if (!aStr || (aStr && isNumber(aStr)==0))
       
   870 		return Print(EError, "Number required as argument for keyword 'code-align'.\n");
       
   871     iCodeAlignment=getNumber(aStr);
       
   872     return KErrNone;
       
   873 	}
       
   874 
       
   875 TInt TRomBuilderEntry::SetDataAlignment(TText* aStr)
       
   876 	{
       
   877     if (!isNumber(aStr))
       
   878 		return Print(EError, "Number required as argument for keyword 'data-align'.\n");
       
   879     TInt align=getNumber(aStr);
       
   880 	if (align<0 || (align&0x0F) != 0)
       
   881 		return Print(EError, "Positive multiple of 16 required for 'data-align'.\n");
       
   882 	iDataAlignment=align;
       
   883     return KErrNone;
       
   884 	}
       
   885 
       
   886 TInt TRomBuilderEntry::SetRelocationAddress(TText *aStr)
       
   887 	{
       
   888 	if (aStr && isNumber(aStr)==0)
       
   889 		return Print(EError, "Number required as argument for keyword 'reloc'.\n");
       
   890 	iOverrideFlags |= KOverrideAddress;
       
   891 	iRelocationAddress=aStr ? getNumber(aStr) : 0xFFFFFFFF;
       
   892 	return KErrNone;
       
   893 	}
       
   894 
       
   895 TInt TRomBuilderEntry::SetStackReserve(TText *aStr)
       
   896 	{
       
   897 	if (isNumber(aStr)==0)
       
   898 		return Print(EError, "Number required as argument for keyword 'stackreserve'.\n");
       
   899 	iOverrideFlags |= KOverrideStackReserve;
       
   900 	iStackReserve=getNumber(aStr);
       
   901 	return KErrNone;
       
   902 	}
       
   903 
       
   904 TInt TRomBuilderEntry::SetStackSize(TText *aStr)
       
   905 	{
       
   906 	if (isNumber(aStr)==0)
       
   907 		return Print(EError, "Number required as argument for keyword 'stack'.\n");
       
   908 	iOverrideFlags |= KOverrideStack;
       
   909 	iStackSize=getNumber(aStr);
       
   910 	return KErrNone;
       
   911 	}
       
   912 
       
   913 TInt TRomBuilderEntry::SetHeapSizeMin(TText *aStr)
       
   914 	{
       
   915 	if (isNumber(aStr)==0)
       
   916 		return Print(EError, "Number required as argument for keyword 'heapmin'.\n");
       
   917 	iOverrideFlags |= KOverrideHeapMin;
       
   918 	iHeapSizeMin=getNumber(aStr);
       
   919 	return KErrNone;
       
   920 	}
       
   921 
       
   922 TInt TRomBuilderEntry::SetHeapSizeMax(TText *aStr)
       
   923 	{
       
   924 	if (isNumber(aStr)==0)
       
   925 		return Print(EError, "Number required as argument for keyword 'heapmax'.\n");
       
   926 	iOverrideFlags |= KOverrideHeapMax;
       
   927 	iHeapSizeMax=getNumber(aStr);
       
   928 	return KErrNone;
       
   929 	}
       
   930 
       
   931 TInt TRomBuilderEntry::SetCapability(TText *aStr)
       
   932 	{
       
   933 	iOverrideFlags |= KOverrideCapability;
       
   934 	if (isNumber(aStr))
       
   935 		{
       
   936 		Print(EDiagnostic,"Old style numeric CAPABILTY specification ignored.\n");
       
   937 		return KErrNone;
       
   938 		}
       
   939 	return ParseCapabilitiesArg(iS.iCaps, (char*)aStr);
       
   940 	}
       
   941 
       
   942 TInt TRomBuilderEntry::SetPriority(TText *aStr)
       
   943 	{
       
   944 	if (isNumber(aStr))
       
   945 		iPriority=(TProcessPriority)getNumber(aStr);
       
   946 	else
       
   947 		{
       
   948 		char *str=(char *)aStr;
       
   949 		if (stricmp(str, "low")==0)
       
   950 			iPriority=EPriorityLow;
       
   951 		else if (strnicmp(str, "background", 4)==0)
       
   952 			iPriority=EPriorityBackground;
       
   953 		else if (strnicmp(str, "foreground", 4)==0)
       
   954 			iPriority=EPriorityForeground;
       
   955 		else if (stricmp(str, "high")==0)
       
   956 			iPriority=EPriorityHigh;
       
   957 		else if (strnicmp(str, "windowserver",3)==0)
       
   958 			iPriority=EPriorityWindowServer;
       
   959 		else if (strnicmp(str, "fileserver",4)==0)
       
   960 			iPriority=EPriorityFileServer;
       
   961 		else if (strnicmp(str, "realtimeserver",4)==0)
       
   962 			iPriority=EPriorityRealTimeServer;
       
   963 		else if (strnicmp(str, "supervisor",3)==0)
       
   964 			iPriority=EPrioritySupervisor;
       
   965 		else
       
   966 			return Print(EError, "Unrecognised priority keyword.\n");
       
   967 		}
       
   968 	if (iPriority<EPriorityLow || iPriority>EPrioritySupervisor)
       
   969 		return Print(EError, "Priority out of range.\n");
       
   970 	iOverrideFlags |= KOverridePriority;
       
   971 	return KErrNone;
       
   972 	}
       
   973 
       
   974 TInt TRomBuilderEntry::SetUid1(TText *aStr)
       
   975 	{
       
   976 	if (isNumber(aStr)==0)
       
   977 		return Print(EError, "Number required as argument for keyword 'uid1'.\n");
       
   978 	iOverrideFlags |= KOverrideUid1;
       
   979 	iUid1=getNumber(aStr);
       
   980 	return KErrNone;
       
   981 	}
       
   982 TInt TRomBuilderEntry::SetUid2(TText *aStr)
       
   983 	{
       
   984 	if (isNumber(aStr)==0)
       
   985 		return Print(EError, "Number required as argument for keyword 'uid2'.\n");
       
   986 	iOverrideFlags |= KOverrideUid2;
       
   987 	iUid2=getNumber(aStr);
       
   988 	return KErrNone;
       
   989 	}
       
   990 TInt TRomBuilderEntry::SetUid3(TText *aStr)
       
   991 	{
       
   992 	if (isNumber(aStr)==0)
       
   993 		return Print(EError, "Number required as argument for keyword 'uid3'.\n");
       
   994 	iOverrideFlags |= KOverrideUid3;
       
   995 	iUid3=getNumber(aStr);
       
   996 	return KErrNone;
       
   997 	}
       
   998 TInt TRomBuilderEntry::SetCallEntryPoint(TBool aState)
       
   999 	{
       
  1000 	if (aState)
       
  1001 		iOverrideFlags|=KOverrideCallEntryPoint;
       
  1002 	else
       
  1003 		iOverrideFlags|=KOverrideNoCallEntryPoint;
       
  1004 	return KErrNone;
       
  1005 	}
       
  1006 
       
  1007 TInt TRomBuilderEntry::SetAttachProcess(TText *aStr)
       
  1008 	{
       
  1009 	const char* s=(const char*)aStr;
       
  1010 	TInt nd=0;
       
  1011 	if (*s=='\\')
       
  1012 		{
       
  1013 		++s;
       
  1014 		++nd;
       
  1015 		}
       
  1016 	TInt l=strlen(s);
       
  1017 	if (l==0)
       
  1018 		return KErrGeneral;
       
  1019 	const char* ss=s;
       
  1020 	while(*ss!=0 && *ss!='.') ++ss;
       
  1021 	int ext=*ss;	// 0 if no extension
       
  1022 	iProcessName=new TText[l+2+(ext?0:4)];
       
  1023 	char* d=(char *)iProcessName;
       
  1024 	strcpy(d+1, s);
       
  1025 	if (!ext)
       
  1026 		{
       
  1027 		char* t=d+1+l;
       
  1028 		*t++='.';
       
  1029 		*t++='e';
       
  1030 		*t++='x';
       
  1031 		*t++='e';
       
  1032 		*t++=0;
       
  1033 		}
       
  1034 	char* dd=d;
       
  1035 	int ind=nd;
       
  1036 	while(*dd)
       
  1037 		{
       
  1038 		while(*dd && *dd!='\\') ++dd;
       
  1039 		if (*dd=='\\')
       
  1040 			{
       
  1041 			*dd++=0;	// change \ to NUL
       
  1042 			++nd;		// count path elements
       
  1043 			}
       
  1044 		}
       
  1045 	if (!ind && nd)
       
  1046 		++nd;			// add initial \ if not present
       
  1047 	*d=(char)nd;
       
  1048 	return 0;
       
  1049 	}
       
  1050 
       
  1051 TInt TRomBuilderEntry::OpenImageFile()
       
  1052 	{
       
  1053 	Print(ELog,"Loading E32Image file %s \n", iFileName);
       
  1054 	TInt err = Open(iFileName);
       
  1055 	if (err != KErrNone)
       
  1056 		{
       
  1057 		Print(EError,"File %s is not a valid E32Image file (error %d)\n", iFileName, err);
       
  1058 		return err;
       
  1059 		}
       
  1060 	TUint hdrfmt = iHdr->HeaderFormat();
       
  1061 	if (hdrfmt != KImageHdrFmt_V)
       
  1062 		{
       
  1063 		Print(EError,"%s: Can't load old format binary\n", iFileName);
       
  1064 		return KErrNotSupported;
       
  1065 		}
       
  1066 	E32ImageHeaderV* h = iHdr;
       
  1067 	
       
  1068 	// Overide any settings in the image file with those in the obey file
       
  1069 	if (iOverrideFlags & (KOverrideUid1|KOverrideUid2|KOverrideUid3))
       
  1070 		{
       
  1071 		TUint uid1 = h->iUid1;
       
  1072 		TUint uid2 = h->iUid2;
       
  1073 		TUint uid3 = h->iUid3;
       
  1074 		if (iOverrideFlags & KOverrideUid1)
       
  1075 			uid1 = iUid1;
       
  1076 		if (iOverrideFlags & KOverrideUid2)
       
  1077 			uid2 = iUid2;
       
  1078 		if (iOverrideFlags & KOverrideUid3)
       
  1079 			uid3 = iUid3;
       
  1080 		SetUids(TUid::Uid(uid1), TUid::Uid(uid2), TUid::Uid(uid3));
       
  1081 		}
       
  1082 	if (iOverrideFlags & KOverrideStack)
       
  1083 		h->iStackSize = iStackSize;
       
  1084 	if (iOverrideFlags & KOverrideHeapMax)
       
  1085 		h->iHeapSizeMax = iHeapSizeMax;
       
  1086 	if (iOverrideFlags & KOverrideHeapMin)
       
  1087 		h->iHeapSizeMin = iHeapSizeMin;
       
  1088 	if (iOverrideFlags & KOverridePriority)
       
  1089 		h->iProcessPriority = (TUint16)iPriority;
       
  1090 	if (iOverrideFlags & KOverrideCapability)
       
  1091 		h->iS.iCaps = iS.iCaps;
       
  1092 	for (TInt i=0; i<SCapabilitySet::ENCapW; ++i)
       
  1093 		{
       
  1094 		h->iS.iCaps[i] |= gPlatSecDisabledCaps[i];
       
  1095 		h->iS.iCaps[i] &= gPlatSecAllCaps[i];
       
  1096 		}
       
  1097 
       
  1098 	if (iOverrideFlags & KOverrideCodePaged)
       
  1099 		{
       
  1100 		h->iFlags &= ~KImageCodeUnpaged;
       
  1101 		h->iFlags |= KImageCodePaged;
       
  1102 		}
       
  1103 	if (iOverrideFlags & KOverrideCodeUnpaged)
       
  1104 		{
       
  1105 		h->iFlags |= KImageCodeUnpaged;
       
  1106 		h->iFlags &= ~KImageCodePaged;
       
  1107 		}
       
  1108 
       
  1109 	if ((TInt)h->iUid1 == KExecutableImageUidValue)
       
  1110 		{
       
  1111 		if (iOverrideFlags & KOverrideDataPaged)
       
  1112 			{
       
  1113 			h->iFlags &= ~KImageDataUnpaged;
       
  1114 			h->iFlags |= KImageDataPaged;
       
  1115 			}
       
  1116 		if (iOverrideFlags & KOverrideDataUnpaged)
       
  1117 			{
       
  1118 			h->iFlags |= KImageDataUnpaged;
       
  1119 			h->iFlags &= ~KImageDataPaged;
       
  1120 			}
       
  1121 		}
       
  1122 
       
  1123 	switch(gCodePagingOverride)
       
  1124 		{
       
  1125 	case EKernelConfigPagingPolicyNoPaging:
       
  1126 		h->iFlags |= KImageCodeUnpaged;
       
  1127 		h->iFlags &= ~KImageCodePaged;
       
  1128 		break;
       
  1129 	case EKernelConfigPagingPolicyAlwaysPage:
       
  1130 		h->iFlags |= KImageCodePaged;
       
  1131 		h->iFlags &= ~KImageCodeUnpaged;
       
  1132 		break;
       
  1133 	case EKernelConfigPagingPolicyDefaultUnpaged:
       
  1134 		if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
       
  1135 			h->iFlags |= KImageCodeUnpaged;
       
  1136 		break;
       
  1137 	case EKernelConfigPagingPolicyDefaultPaged:
       
  1138 		if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
       
  1139 			h->iFlags |= KImageCodePaged;
       
  1140 		break;
       
  1141 		}
       
  1142 	switch(gDataPagingOverride)
       
  1143 		{
       
  1144 	case EKernelConfigPagingPolicyNoPaging:
       
  1145 		h->iFlags |= KImageDataUnpaged;
       
  1146 		h->iFlags &= ~KImageDataPaged;
       
  1147 		break;
       
  1148 	case EKernelConfigPagingPolicyAlwaysPage:
       
  1149 		h->iFlags |= KImageDataPaged;
       
  1150 		h->iFlags &= ~KImageDataUnpaged;
       
  1151 		break;
       
  1152 	case EKernelConfigPagingPolicyDefaultUnpaged:
       
  1153 		if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
       
  1154 			h->iFlags |= KImageDataUnpaged;
       
  1155 		break;
       
  1156 	case EKernelConfigPagingPolicyDefaultPaged:
       
  1157 		if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
       
  1158 			h->iFlags |= KImageDataPaged;
       
  1159 		break;
       
  1160 		}
       
  1161 	
       
  1162 	h->iCompressionType=KUidCompressionDeflate; // XIP images are always uncompressed
       
  1163 	
       
  1164 	Print(ELog,"\t\tcompression format:0x%08x \n", h->iCompressionType);
       
  1165 	if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
       
  1166 		Print(ELog,"\t\tgCompress:%d, gCompressionMethod: 0x%08x \n", gEnableCompress , gCompressionMethod);
       
  1167 
       
  1168 
       
  1169 	// Check the uids
       
  1170 
       
  1171 	if ((TInt)h->iUid1 != KExecutableImageUidValue && (TInt)h->iUid1 != KDynamicLibraryUidValue) 
       
  1172 		return Print(EError, "First Uid for %s is not KExecutableImageUid or KDynamicLibraryUid\n", iFileName);
       
  1173 
       
  1174 	// Set up the sizes and location of the distinct areas
       
  1175 
       
  1176 	iHeaderRange.iSize = sizeof(TRomImageHeader);
       
  1177 
       
  1178 	iCodeSection.iSize    = h->iTextSize;
       
  1179 	iCodeSection.iFilePtr = iData + iOrigHdr->iCodeOffset;
       
  1180 
       
  1181 	TUint impfmt = h->ImportFormat();
       
  1182 
       
  1183 	if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
       
  1184 		{
       
  1185 		TInt nimports = NumberOfImports();
       
  1186 		if (nimports)
       
  1187 			{
       
  1188 			iImportAddressTableSection.iSize    = (nimports+1)*4;
       
  1189 			iImportAddressTableSection.iFilePtr = iData + iOrigHdr->iCodeOffset + iOrigHdr->iTextSize;
       
  1190 			iIATRefs = new TLinAddr*[nimports+1];
       
  1191 			memcpy(iIATRefs, iImportAddressTableSection.iFilePtr, (nimports+1)*sizeof(TLinAddr*));
       
  1192 			}
       
  1193 
       
  1194 		if (h->iExportDirCount)
       
  1195 			{
       
  1196 			iExportDirSection.iSize    = h->iExportDirCount*4;
       
  1197 			iExportDirSection.iFilePtr = iData + iOrigHdr->iExportDirOffset;
       
  1198 			}
       
  1199 
       
  1200 		// assertion - there's no rdata between IAT and Export Directory
       
  1201 		TInt rdatasize = h->iCodeSize;		// overall "readonly" size
       
  1202 		rdatasize -= iCodeSection.iSize;				// text
       
  1203 		rdatasize -= iImportAddressTableSection.iSize;	// IAT plus trailing 0
       
  1204 		rdatasize -= iExportDirSection.iSize;			// export data
       
  1205 
       
  1206 		if (rdatasize != 0)
       
  1207 			{
       
  1208 			Print(EWarning, "Unexpected code in %s: %d bytes unexplained\n", iFileName, rdatasize);
       
  1209 			// expand the code to cover text+IAT+rdata
       
  1210 			iCodeSection.iSize = h->iCodeSize - iExportDirSection.iSize;
       
  1211 			}
       
  1212 		else
       
  1213 			{
       
  1214 			if (USE_IAT_FOR_IMPORTS)
       
  1215 				iCodeSection.iSize += iImportAddressTableSection.iSize;	// include IAT
       
  1216 			}
       
  1217 		}
       
  1218 	else
       
  1219 		{
       
  1220 		// ELF-derived images have no IAT and the export directory is included in the code section
       
  1221 		iImportAddressTableSection.iSize    = 0;
       
  1222 		iImportAddressTableSection.iFilePtr = NULL;
       
  1223 		iExportDirSection.iSize    = 0;
       
  1224 		iExportDirSection.iFilePtr = NULL;
       
  1225 		}
       
  1226 
       
  1227 	if (h->iDataSize)
       
  1228 		{
       
  1229 		iDataSection.iSize    = h->iDataSize;
       
  1230 		iDataSection.iFilePtr = iData + iOrigHdr->iDataOffset;
       
  1231 		}
       
  1232 
       
  1233 	iRomNode->iRomFile->iTotalDataBss = h->iDataSize + h->iBssSize;
       
  1234 	iS = h->iS;
       
  1235 	if (iVersionPresentInName && iVersionInName != h->ModuleVersion())
       
  1236 		{
       
  1237 		Print(EError,"%s: Version in name (%d.%d) does not match version in header (%d.%d)\n", iFileName,
       
  1238 			iVersionInName>>16, iVersionInName&0x0000ffffu, h->ModuleVersion()>>16, h->ModuleVersion()&0x0000ffffu);
       
  1239 		return KErrGeneral;
       
  1240 		}
       
  1241 	return KErrNone;
       
  1242 	}
       
  1243 
       
  1244 TInt TRomNode::NameCpy(char* aDest)
       
  1245 //
       
  1246 // Safely copy a file name in the rom entry
       
  1247 //
       
  1248 	{
       
  1249 
       
  1250 	if ((aDest==NULL) || (iName==NULL))
       
  1251 		return 0;
       
  1252 	if (Unicode)
       
  1253 		{
       
  1254 		const unsigned char* pSourceByte=iName;
       
  1255 		unsigned char* pTargetByte=(unsigned char*)aDest;
       
  1256 		for (;;)
       
  1257 			{
       
  1258 			const TUint sourceByte=*pSourceByte;
       
  1259 			if (sourceByte==0)
       
  1260 				{
       
  1261 				*pTargetByte=0;
       
  1262 				*(pTargetByte+1)=0;
       
  1263 				break;
       
  1264 				}
       
  1265 			if ((sourceByte&0x80)==0)
       
  1266 				{
       
  1267 				*pTargetByte=(unsigned char)sourceByte;
       
  1268 				++pTargetByte;
       
  1269 				*pTargetByte=0;
       
  1270 				++pTargetByte;
       
  1271 				++pSourceByte;
       
  1272 				}
       
  1273 			else if ((sourceByte&0xe0)==0xc0)
       
  1274 				{
       
  1275 				++pSourceByte;
       
  1276 				const TUint secondSourceByte=*pSourceByte;
       
  1277 				if ((secondSourceByte&0xc0)!=0x80)
       
  1278 					{
       
  1279 					Print(EError, "Bad UTF-8 '%s'", iName);
       
  1280 					exit(671);
       
  1281 					}
       
  1282 				*pTargetByte=(unsigned char)((secondSourceByte&0x3f)|((sourceByte&0x03)<<6));
       
  1283 				++pTargetByte;
       
  1284 				*pTargetByte=(unsigned char)((sourceByte>>2)&0x07);
       
  1285 				++pTargetByte;
       
  1286 				++pSourceByte;
       
  1287 				}
       
  1288 			else if ((sourceByte&0xf0)==0xe0)
       
  1289 				{
       
  1290 				++pSourceByte;
       
  1291 				const TUint secondSourceByte=*pSourceByte;
       
  1292 				if ((secondSourceByte&0xc0)!=0x80)
       
  1293 					{
       
  1294 					Print(EError, "Bad UTF-8 '%s'", iName);
       
  1295 					exit(672);
       
  1296 					}
       
  1297 				++pSourceByte;
       
  1298 				const TUint thirdSourceByte=*pSourceByte;
       
  1299 				if ((thirdSourceByte&0xc0)!=0x80)
       
  1300 					{
       
  1301 					Print(EError, "Bad UTF-8 '%s'", iName);
       
  1302 					exit(673);
       
  1303 					}
       
  1304 				*pTargetByte=(unsigned char)((thirdSourceByte&0x3f)|((secondSourceByte&0x03)<<6));
       
  1305 				++pTargetByte;
       
  1306 				*pTargetByte=(unsigned char)(((secondSourceByte>>2)&0x0f)|((sourceByte&0x0f)<<4));
       
  1307 				++pTargetByte;
       
  1308 				++pSourceByte;
       
  1309 				}
       
  1310 			else
       
  1311 				{
       
  1312 				Print(EError, "Bad UTF-8 '%s'", iName);
       
  1313 				exit(674);
       
  1314 				}
       
  1315 			}
       
  1316 		const TInt numberOfBytesInTarget=(pTargetByte-(unsigned char*)aDest); // this number excludes the trailing null-terminator
       
  1317 		if (numberOfBytesInTarget%2!=0)
       
  1318 			{
       
  1319 			Print(EError, "Internal error");
       
  1320 			exit(675);
       
  1321 			}
       
  1322 		return numberOfBytesInTarget/2; // returns the length of aDest (in UTF-16 characters for Unicode, not bytes)
       
  1323 		}
       
  1324 	strcpy(aDest,(const char*)iName);
       
  1325 	return strlen((const char*)iName);
       
  1326 	}
       
  1327 
       
  1328 TInt TRomBuilderEntry::SizeInRom()
       
  1329 //
       
  1330 // Approximate the required size of the file when rommed
       
  1331 //
       
  1332 	{
       
  1333 
       
  1334 	TInt size1, size2;
       
  1335 	SizeInSections(size1,size2);
       
  1336 	return size1+size2;
       
  1337 	}
       
  1338 
       
  1339 void TRomBuilderEntry::LoadToRom()
       
  1340 //
       
  1341 //
       
  1342 //
       
  1343 	{
       
  1344 	// Copy fixed stuff into iRomImageHeader
       
  1345 	E32ImageHeaderV* h = iHdr;
       
  1346 	const TUint KRomFlagMask = KImageDll | KImageNoCallEntryPoint | KImageFixedAddressExe | KImageNmdExpData | KImageDataPagingMask;
       
  1347 	TUint romflags = h->iFlags & KRomFlagMask;
       
  1348 	TUint abi = h->ABI();
       
  1349 	TUint ept = h->EntryPointFormat();
       
  1350 	TUint impfmt = h->ImportFormat();
       
  1351 	romflags |= (abi | ept);
       
  1352 
       
  1353 	iRomImageHeader = (TRomImageHeader*)iHeaderRange.iImagePtr;
       
  1354 
       
  1355 	iRomImageHeader->iUid1              = h->iUid1;
       
  1356 	iRomImageHeader->iUid2              = h->iUid2;
       
  1357 	iRomImageHeader->iUid3              = h->iUid3;
       
  1358 	iRomImageHeader->iUidChecksum       = h->iUidChecksum;
       
  1359 	iRomImageHeader->iEntryPoint        = iCodeSection.iRunAddr + h->iEntryPoint;
       
  1360 	iRomImageHeader->iCodeAddress       = iCodeSection.iRunAddr;
       
  1361 	iRomImageHeader->iDataAddress       = iDataSection.iRunAddr;
       
  1362 	iRomImageHeader->iCodeSize          = iCodeSection.iSize+iExportDirSection.iSize;
       
  1363 	iRomImageHeader->iTextSize          = iCodeSection.iSize;
       
  1364 	iRomImageHeader->iDataSize          = iDataSection.iSize;
       
  1365 	iRomImageHeader->iBssSize           = h->iBssSize;
       
  1366 	iRomImageHeader->iTotalDataSize		= iRomNode->iRomFile->iTotalDataBss;
       
  1367 	iRomImageHeader->iHeapSizeMin       = h->iHeapSizeMin;
       
  1368 	iRomImageHeader->iHeapSizeMax       = h->iHeapSizeMax;
       
  1369 	iRomImageHeader->iStackSize         = h->iStackSize;
       
  1370 	iRomImageHeader->iDllRefTable       = (TDllRefTable*)(iDllRefTableRange.iImageAddr);
       
  1371 	iRomImageHeader->iExportDirCount    = h->iExportDirCount;
       
  1372 	iRomImageHeader->iExportDir         = (impfmt==KImageImpFmt_ELF) ?
       
  1373 											iCodeSection.iRunAddr + (h->iExportDirOffset - h->iCodeOffset)
       
  1374 											: iExportDirSection.iRunAddr;
       
  1375 	iRomImageHeader->iS					= h->iS;
       
  1376 	iRomImageHeader->iToolsVersion		= h->iToolsVersion;
       
  1377 	iRomImageHeader->iModuleVersion		= h->ModuleVersion();
       
  1378 	iRomImageHeader->iFlags             = romflags | iRomImageFlags;
       
  1379 	iRomImageHeader->iPriority          = h->ProcessPriority();
       
  1380 	iRomImageHeader->iDataBssLinearBase = iDataBssLinearBase;
       
  1381 	iRomImageHeader->iNextExtension     = 0;
       
  1382 	iRomImageHeader->iHardwareVariant   = iHardwareVariant;
       
  1383 	iRomImageHeader->iExceptionDescriptor = 0;
       
  1384 	TUint32 xd = h->iExceptionDescriptor;
       
  1385 	if ((xd & 1) && (xd != 0xffffffffu))
       
  1386 		iRomImageHeader->iExceptionDescriptor = (xd & ~1) + iRomImageHeader->iCodeAddress;
       
  1387 
       
  1388 	if (iPreferred)
       
  1389 		{
       
  1390 		iRomImageHeader->iModuleVersion	&= ~0xffffu;
       
  1391 		iRomImageHeader->iModuleVersion	|= 0x8000u;
       
  1392 		}
       
  1393 
       
  1394 	// Relocate the file to reflect the new addresses
       
  1395 	Relocate();
       
  1396 
       
  1397 	// Copy the sections
       
  1398 	iCodeSection.Load();
       
  1399 	iExportDirSection.Load();
       
  1400 	iDataSection.Load();
       
  1401 	}
       
  1402 
       
  1403 void TRomBuilderEntry::Relocate()
       
  1404 //
       
  1405 // Relocates the iData to new Code and Data addresses
       
  1406 //	
       
  1407 	{
       
  1408 	TUint codeDelta=iRomImageHeader->iCodeAddress       - iHdr->iCodeBase;
       
  1409 	TUint dataDelta=iRomImageHeader->iDataBssLinearBase - iHdr->iDataBase;
       
  1410 
       
  1411 	// code section (text, IAT, export directory)
       
  1412 
       
  1413 	if (iOrigHdr->iCodeRelocOffset)
       
  1414 		RelocateSection(iData + iOrigHdr->iCodeOffset, iData + iOrigHdr->iCodeRelocOffset,
       
  1415 			codeDelta, dataDelta, (char*)iCodeSection.iImagePtr, iIATRefs);
       
  1416 
       
  1417 	// data section 
       
  1418 
       
  1419 	if (iOrigHdr->iDataRelocOffset)
       
  1420 		RelocateSection(iData + iOrigHdr->iDataOffset, iData + iOrigHdr->iDataRelocOffset, 
       
  1421 			codeDelta, dataDelta, (char*)iDataSection.iImagePtr, iIATRefs);
       
  1422 
       
  1423 	// export directory (only for PE-derived files)
       
  1424 	if (iExportDirSection.iSize)
       
  1425 		{
       
  1426 		TLinAddr* ptr=(TLinAddr*)(iData + iOrigHdr->iExportDirOffset);
       
  1427 
       
  1428 		TLinAddr textStart = iHdr->iCodeBase;
       
  1429 		TLinAddr textFinish = textStart + iHdr->iTextSize;
       
  1430 		TLinAddr dataStart = textStart + iHdr->iCodeSize;
       
  1431 		TLinAddr dataFinish = dataStart + iHdr->iDataSize + iHdr->iBssSize;
       
  1432 	 
       
  1433 		TInt i;
       
  1434 		for (i=0; i<iHdr->iExportDirCount; i++, ptr++)
       
  1435 			{
       
  1436 			TLinAddr data=*ptr+textStart;
       
  1437 			if ((data>=textStart) && (data<textFinish))
       
  1438 				*ptr=data+codeDelta; // export something from the text/rdata section
       
  1439 			else if ((data>=dataStart) && (data<dataFinish))
       
  1440 				*ptr=data+dataDelta; // export some data or bss item
       
  1441 			else
       
  1442 				{
       
  1443 				Print(EWarning, "Export directory in %s: item %d -> %08x, which is not text or data!\n", iFileName, i, data);
       
  1444 				*ptr=0x13;	// unlucky for some
       
  1445 				}
       
  1446 			}
       
  1447 		}
       
  1448 
       
  1449 	// Replace absent exports with 0
       
  1450 	TLinAddr* ptr = (TLinAddr*)(iData + iOrigHdr->iExportDirOffset);
       
  1451 	TInt i;
       
  1452 	for (i=0; i<iHdr->iExportDirCount; i++, ptr++)
       
  1453 		{
       
  1454 		if ( !( iExportBitMap[i>>3] & (1u << (i&7)) ) )
       
  1455 			*ptr = 0;
       
  1456 		}
       
  1457 
       
  1458 	// Update E32ImageHeader, in case we want to do this process again later
       
  1459 
       
  1460 	iHdr->iCodeBase += codeDelta;
       
  1461 	iHdr->iDataBase += dataDelta;
       
  1462 	}
       
  1463 
       
  1464 
       
  1465 
       
  1466 
       
  1467 TInt TRomBuilderEntry::FixupImports(E32Rom& aRom)
       
  1468 //
       
  1469 // Modify the import stubs to point directly into the export directory of the corresponding DLLs
       
  1470 // using the back pointers captured by detecting relocations referring to the Import Address Table
       
  1471 // The old-style Import Address Table behaviour can be retained by specifying the "keepIAT" attribute.
       
  1472 //
       
  1473 	{
       
  1474 	if (iHdr->iImportOffset == 0)
       
  1475 		return KErrNone;	// nothing to do
       
  1476 
       
  1477 	
       
  1478 
       
  1479 	TUint impfmt = iHdr->ImportFormat();
       
  1480 	TUint my_abi = iHdr->ABI();
       
  1481 	TRACE(TIMPORT,Print(ELog,"%40s[%08x] flags %08x\n",iFileName,(TUint)iHardwareVariant,iHdr->iFlags));
       
  1482 	const E32ImportSection* importsection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
       
  1483 	TLinAddr **iatRef=iIATRefs;
       
  1484 	TAddressRange iatRange = iCodeSection;
       
  1485 	iatRange.Move(iHdr->iTextSize);
       
  1486 	if (USE_IAT_FOR_IMPORTS)
       
  1487 		{
       
  1488 		if (impfmt == KImageImpFmt_ELF)
       
  1489 			return Print(EError, "Can't retain IAT for %s since it never existed\n", iFileName);
       
  1490 		if (iRomSectionNumber==0 && aRom.iObey->iSectionPosition!=-1)
       
  1491 			return Print(EError, "Can't retain IAT for %s in first section - not yet implemented\n", iFileName);
       
  1492 		Print(ELog, "%s has IAT at %08x\n", iFileName, iatRange.iRunAddr);
       
  1493 		}
       
  1494 	const E32ImportBlock* b = (const E32ImportBlock*)(importsection + 1);
       
  1495 	TInt i = iHdr->iDllRefTableCount;
       
  1496 	TInt numberOfImports=0;
       
  1497 	TUint *impOrdinalP = (TUint*)iImportAddressTableSection.iFilePtr;	// points to original IAT in file
       
  1498 	while (i-->0)
       
  1499 		{
       
  1500 		char* dllname = (char*)importsection + b->iOffsetOfDllName;
       
  1501 		TDllFindInfo find_info(dllname, this);
       
  1502 		TBool fallback;
       
  1503 		TRomNode* romnode = aRom.FindImageFileByName(find_info, EFalse, fallback);
       
  1504 		if (!romnode)
       
  1505 			{
       
  1506 			Print(EError, "Can't fixup imports for\n\t%s\nbecause\n\t%s\nis not in rom.\n",
       
  1507 						 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1508 			aRom.FindImageFileByName(find_info, ETrue, fallback);
       
  1509 			return KErrGeneral;
       
  1510 			}
       
  1511 		TRomFile* dll=romnode->iRomFile;
       
  1512 		TRACE(TIMPORT,Print(ELog,"%s importing from %s\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info)));
       
  1513 		if (romnode->ABI() != my_abi)
       
  1514 			{
       
  1515 			Print(EWarning, "File %s links to %s with different ABI\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1516 			}
       
  1517 		TInt j;
       
  1518 		numberOfImports += b->iNumberOfImports;
       
  1519 		if (impfmt==KImageImpFmt_ELF)
       
  1520 			impOrdinalP = (TUint*)(b->Imports());	// for ELF must look in import block
       
  1521 		char* codeBase = (char*)iCodeSection.iImagePtr;
       
  1522 		for (j=0; j<b->iNumberOfImports; j++)
       
  1523 			{
       
  1524 			TLinAddr exportAddr = 0xdeadbeef;
       
  1525 			TLinAddr exporter = 0xdeadbeef;
       
  1526 			TUint impOrdinal = *impOrdinalP;
       
  1527 			TUint impOffset = 0;
       
  1528 			if (impfmt==KImageImpFmt_ELF)
       
  1529 				{
       
  1530 				TUint impd = *(TUint*)(codeBase + impOrdinal);
       
  1531 				impOrdinal = impd & 0xffff;
       
  1532 				impOffset = impd >> 16;
       
  1533 				}
       
  1534 			TRACE(TIMPORT,Print(ELog,"Ordinal %d\n", impOrdinal));
       
  1535 			TInt ret=dll->AddressFromOrdinal(exporter, exportAddr, impOrdinal);
       
  1536 			TRACE(TIMPORT,Print(ELog,"export %08x exporter %08x\n",exportAddr,exporter));
       
  1537 			if (ret!=KErrNone)
       
  1538 				{
       
  1539 				Print(EError, "%s wants ordinal %d from %s which only exports %d functions\n",
       
  1540 					iFileName, impOrdinal, 	(const char*)TModuleName(find_info), dll->ExportDirCount());
       
  1541 				exporter=0x13;	// unlucky for some...
       
  1542 				exportAddr=0x13;
       
  1543 				}
       
  1544 			else if (exportAddr == 0 && impOrdinal != 0)
       
  1545 				{
       
  1546 				Print(EError, "%s wants ordinal %d from %s which is absent\n",
       
  1547 					iFileName, impOrdinal, 	(const char*)TModuleName(find_info));
       
  1548 				exporter=0x13;	// unlucky for some...
       
  1549 				exportAddr=0x13;
       
  1550 				}
       
  1551 			if (USE_IAT_FOR_IMPORTS)
       
  1552 				{
       
  1553 				// must be PE-derived
       
  1554 				*iatRef=(unsigned long*)exportAddr; //iatRange.iRunAddr;					// point into IAT ...
       
  1555 				*(TLinAddr*)(iatRange.iImagePtr)=exportAddr;	// ... which has a copy of the export
       
  1556 				iatRange.Move(sizeof(TLinAddr));
       
  1557 				iatRef++;
       
  1558 				}
       
  1559 			else if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
       
  1560 				{
       
  1561 				**iatRef=exporter;	// point directly into export directory
       
  1562 				iatRef++;
       
  1563 				}
       
  1564 			else
       
  1565 				{
       
  1566 				// ELF-derived
       
  1567 				*(TUint*)(codeBase + *impOrdinalP) = exportAddr + impOffset;
       
  1568 				}
       
  1569 			impOrdinalP++;
       
  1570 			}
       
  1571 		b = b->NextBlock(impfmt);
       
  1572 		}
       
  1573 	iImportCount=numberOfImports;
       
  1574 	return KErrNone;
       
  1575 	}
       
  1576 
       
  1577 const char* KF32ProcessName="efile.exe";
       
  1578 const char* KWservProcessName="ewsrv.exe";
       
  1579 const char* KFbservProcessName="fbserv.exe";
       
  1580 const char* KMdaSvrProcessName="mediaserverstub.exe";
       
  1581 const char* KC32ProcessName="c32exe.exe";
       
  1582 
       
  1583 const char* TRomBuilderEntry::GetDefaultAttachProcess()
       
  1584 //
       
  1585 // Work out the attach process from the file extension
       
  1586 //
       
  1587 // Only need to handle DLLs which run in F32, WSERV, FBSERV, MEDIASVR, C32
       
  1588 // F32:		FSY FXT
       
  1589 // WSERV:	ANI
       
  1590 // FBSERV:
       
  1591 // MDASVR:	MDA
       
  1592 // C32:		CSY, PRT, TSY, AGT, AGX
       
  1593 //
       
  1594 	{
       
  1595 	const char* s=(const char*)iName;
       
  1596 	TInt l=strlen(s);
       
  1597 	if (l<4 || s[l-4]!='.')
       
  1598 		return NULL;
       
  1599 	s+=(l-3);
       
  1600 	if (stricmp(s,"fsy")==0)
       
  1601 		return KF32ProcessName;
       
  1602 	if (stricmp(s,"fxt")==0)
       
  1603 		return KF32ProcessName;
       
  1604 	if (stricmp(s,"ani")==0)
       
  1605 		return KWservProcessName;
       
  1606 	if (stricmp(s,"mda")==0)
       
  1607 		return KMdaSvrProcessName;
       
  1608 	if (stricmp(s,"csy")==0)
       
  1609 		return KC32ProcessName;
       
  1610 	if (stricmp(s,"prt")==0)
       
  1611 		return KC32ProcessName;
       
  1612 	if (stricmp(s,"tsy")==0)
       
  1613 		return KC32ProcessName;
       
  1614 	if (stricmp(s,"agt")==0)
       
  1615 		return KC32ProcessName;
       
  1616 	if (stricmp(s,"agx")==0)
       
  1617 		return KC32ProcessName;
       
  1618 	return NULL;
       
  1619 	}
       
  1620 
       
  1621 TInt TRomBuilderEntry::FindAttachProcess(E32Rom& aRom)
       
  1622 	{
       
  1623 	if (iRomImageFlags & (KRomImageFlagVariant|KRomImageFlagExtension|KRomImageFlagDevice))
       
  1624 		return KErrNone;
       
  1625 	const char* attp_name=(const char*)iProcessName;
       
  1626 	int nd=0;
       
  1627 	if (attp_name)
       
  1628 		nd=*attp_name++;
       
  1629 	else
       
  1630 		attp_name=GetDefaultAttachProcess();
       
  1631 	if (!attp_name)
       
  1632 		return KErrNone;
       
  1633 	TInt i;
       
  1634 	TUint my_abi = iHdr->ABI();
       
  1635 	TUint abi = 0;
       
  1636 	if (nd)
       
  1637 		{
       
  1638 		// path search
       
  1639 		TRomNode* rn=aRom.iObey->iRootDirectory;
       
  1640 		for (; nd; --nd)
       
  1641 			{
       
  1642 			rn=rn->FindInDirectory((TText*)attp_name);
       
  1643 			if (!rn)
       
  1644 				{
       
  1645 				Print(EError, "Invalid attach process name element %s\n", attp_name);
       
  1646 				return KErrGeneral;
       
  1647 				}
       
  1648 			attp_name+=(strlen(attp_name)+1);
       
  1649 			}
       
  1650 		iRomNode->iRomFile->iAttachProcess=rn->iRomFile;
       
  1651 		abi = iRomNode->iRomFile->iAttachProcess->ABI();
       
  1652 		}
       
  1653 	else
       
  1654 		{
       
  1655 		// filename only search
       
  1656 		for (i=0; i<aRom.iObey->iNumberOfPeFiles; i++)
       
  1657 			{
       
  1658 			TRomBuilderEntry* e=aRom.iPeFiles[i];
       
  1659 			abi = e->iHdr->ABI();
       
  1660 			if (stricmp((const char*)e->iName, attp_name)==0)
       
  1661 				{
       
  1662 				if (iRomNode->iRomFile->iAttachProcess)
       
  1663 					{
       
  1664 					Print(EError, "Ambiguous attach process name %s\n", attp_name);
       
  1665 					return KErrGeneral;
       
  1666 					}
       
  1667 				iRomNode->iRomFile->iAttachProcess=e->iRomNode->iRomFile;
       
  1668 				}
       
  1669 			}
       
  1670 		}
       
  1671 	if (abi != my_abi)
       
  1672 		{
       
  1673 		Print(EWarning, "File %s: Attach process has different ABI\n", (const char*)TModuleName(this));
       
  1674 		}
       
  1675 	return KErrNone;
       
  1676 	}
       
  1677 
       
  1678 TInt TRomBuilderEntry::BuildDependenceGraph(E32Rom& aRom)
       
  1679 //
       
  1680 // Fill in the iDeps
       
  1681 //
       
  1682 	{
       
  1683 	TBool is_kernel = ((iRomImageFlags & KRomImageFlagsKernelMask) != 0);
       
  1684 	TRomNode* rn = iRomNode;
       
  1685 	TRomFile* rf = rn->iRomFile;
       
  1686 	TUint my_abi = iHdr->ABI();
       
  1687 	TUint impfmt = iHdr->ImportFormat();
       
  1688 	rf->iNumDeps = iHdr->iDllRefTableCount;
       
  1689 	if (IsDll() && aRom.iObey->iMemModel!=E_MM_Flexible && aRom.iObey->iMemModel!=E_MM_Multiple && (iHdr->iDataSize!=0 || iHdr->iBssSize!=0))
       
  1690 		{
       
  1691 		TInt r=FindAttachProcess(aRom);
       
  1692 		if (r!=KErrNone)
       
  1693 			return r;
       
  1694 		if (aRom.iObey->iMemModel==E_MM_Moving)
       
  1695 			{
       
  1696 			if (rf->iAttachProcess && !(rf->iAttachProcess->RomImageFlags() & KRomImageFlagFixedAddressExe))
       
  1697 				rf->iAttachProcess=NULL;	// ignore attach process if not fixed
       
  1698 			}
       
  1699 		}
       
  1700 	TRomFile* attp=rf->iAttachProcess;
       
  1701 	if (attp)
       
  1702 		++rf->iNumDeps;		// extra implicit dependence on process
       
  1703 	if (rf->iNumDeps)
       
  1704 		{
       
  1705 		rf->iDeps=new TRomFile* [rf->iNumDeps];
       
  1706 		memset(rf->iDeps, 0, rf->iNumDeps*sizeof(TRomFile*));
       
  1707 		}
       
  1708 
       
  1709 	TInt err = KErrNone;
       
  1710 	const E32ImportSection* importSection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
       
  1711 	const E32ImportBlock* block = (const E32ImportBlock*)(importSection + 1);
       
  1712 	TInt i;
       
  1713 	for (i=0; i<iHdr->iDllRefTableCount; i++, block = block->NextBlock(impfmt), TRACE(TIMPORT,Print(ELog,"DllRef/dll done\n")) )
       
  1714 		{
       
  1715 		char* dllname = (char*)importSection + block->iOffsetOfDllName;
       
  1716 		TDllFindInfo find_info(dllname, this);
       
  1717 		TBool fallback;
       
  1718 		TRomNode* romnode = aRom.FindImageFileByName(find_info, EFalse, fallback);
       
  1719 		if (!romnode)
       
  1720 			{
       
  1721 			Print(EError, "Can't build dependence graph for\n\t%s\nbecause\n\t%s\nis not in rom.\n",
       
  1722 						 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1723 			aRom.FindImageFileByName(find_info, ETrue, fallback);
       
  1724 			err = KErrNotFound;
       
  1725 			continue;
       
  1726 			}
       
  1727 		if (fallback)
       
  1728 			{
       
  1729 			Print(EWarning, "File %s links to %s\n\twhich is not in ROM. Version 1.0 of latter used instead.\n",
       
  1730 					 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1731 			}
       
  1732 		TRACE(TIMPORT,Print(ELog,"%s links to %s\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info)));
       
  1733 		TRACE(TIMPORT,Print(ELog,"Resolves to %s\n", (const char*)TModuleName(*romnode)));
       
  1734 		TBool dep_is_kernel = ((romnode->iRomFile->RomImageFlags() & KRomImageFlagsKernelMask) != 0);
       
  1735 		if (dep_is_kernel != is_kernel)
       
  1736 			{
       
  1737 			if (is_kernel)
       
  1738 				{
       
  1739 				Print(EError, "Kernel side executable\n\t%s\nlinks to user side executable\n\t%s\n",
       
  1740 									 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1741 				}
       
  1742 			else
       
  1743 				{
       
  1744 				Print(EError, "User side executable\n\t%s\nlinks to kernel side executable\n\t%s\n",
       
  1745 									 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1746 				}
       
  1747 			err = KErrGeneral;
       
  1748 			continue;
       
  1749 			}
       
  1750 		// prevent the situiation which importer is primary, variant or extension, exporter is device
       
  1751 		if (is_kernel && !Device() && romnode->iRomFile->iRbEntry->Device())	
       
  1752 			{
       
  1753 			Print(EWarning, "Kernel/variant/extension\n\t%s\nlinks to non-extension LDD/PDD\n\t%s\n",
       
  1754 							(const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1755 			}
       
  1756 		if (romnode->ABI() != my_abi)
       
  1757 			{
       
  1758 			Print(EWarning, "File %s links to %s with different ABI\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info));
       
  1759 			}
       
  1760 
       
  1761 		rf->iDeps[i]=romnode->iRomFile;
       
  1762 		const SSecurityInfo& s1 = iHdr->iS;
       
  1763 		const SSecurityInfo& s2 = romnode->iRomFile->SecurityInfo();
       
  1764 		TInt r = CompareCapabilities(s1.iCaps, s2.iCaps, iFileName, dllname);
       
  1765 		if (r != KErrNone)
       
  1766 			err = r;
       
  1767 		if (romnode->iRomFile==attp)
       
  1768 			attp=NULL;
       
  1769 		}
       
  1770 
       
  1771 	if (attp)
       
  1772 		rf->iDeps[rf->iNumDeps-1]=attp;
       
  1773 	TRACE(TIMPORT,Print(ELog,"BuildDep done all\n"));
       
  1774 	return err;
       
  1775 	}
       
  1776 
       
  1777 TInt TRomBuilderEntry::ResolveDllRefTable(E32Rom& aRom)
       
  1778 //
       
  1779 // Fill in the DLLRefTable
       
  1780 //
       
  1781 	{
       
  1782 	TRomNode* rn = iRomNode;
       
  1783 	TRomFile* rf = rn->iRomFile;
       
  1784 	(void)aRom;
       
  1785 	if (rf->iNumPDeps==0)
       
  1786 		return KErrNone;	// nothing to do
       
  1787 
       
  1788 	TDllRefTable* dllRefTable=(TDllRefTable*)(iDllRefTableRange.iImagePtr);
       
  1789 
       
  1790 	TUint16 flags=0;
       
  1791 
       
  1792 	dllRefTable->iFlags=flags;
       
  1793 	dllRefTable->iNumberOfEntries=(TUint16)rf->iNumPDeps;
       
  1794 
       
  1795 	TInt err = KErrNone;
       
  1796 	TInt i;
       
  1797 	for (i=0; i<rf->iNumPDeps; i++)
       
  1798 		{
       
  1799 		dllRefTable->iEntry[i]=(TRomImageHeader*)rf->iPDeps[i]->iAddresses.iRunAddr;
       
  1800 		}
       
  1801 	TRACE(TIMPORT,Print(ELog,"DllRef done all\n"));
       
  1802 	return err;
       
  1803 	}
       
  1804 
       
  1805 void TRomBuilderEntry::DisplaySize(TPrintType aWhere)
       
  1806 	{
       
  1807 	if(gLogLevel > DEFAULT_LOG_LEVEL){
       
  1808 
       
  1809 		if(gLogLevel & LOG_LEVEL_FILE_DETAILS)
       
  1810 		{
       
  1811 			// More detailed information about file name in .
       
  1812 			TBool aIgnoreHiddenAttrib = ETrue;
       
  1813 			TInt aLen = iRomNode->FullNameLength(aIgnoreHiddenAttrib);
       
  1814 			char * aBuf = new char[aLen+1];
       
  1815 			iRomNode->GetFullName(aBuf, aIgnoreHiddenAttrib);
       
  1816 			if (iPatched|iRomNode->iHidden)
       
  1817 				Print(aWhere, "%s\t%d\t%s\t%s\n", iFileName, SizeInRom(), iPatched?"patched":"hidden", aBuf);
       
  1818 			else
       
  1819 				Print(aWhere, "%s\t%d\t%s\n", iFileName, SizeInRom(), aBuf);
       
  1820 			delete[] aBuf;
       
  1821 		}
       
  1822 	}
       
  1823 	else{
       
  1824 		if (iPatched|iRomNode->iHidden)
       
  1825 			Print(aWhere, "%s\t%d\t%s\n", iFileName, SizeInRom(), iPatched?"patched":"hidden");
       
  1826 		else
       
  1827 			Print(aWhere, "%s\t%d\n", iFileName, SizeInRom());
       
  1828 	}
       
  1829 	}
       
  1830 
       
  1831 /**
       
  1832  * TRomFile iRomEntry is a linked list through the various
       
  1833  * distinct TRomEntry objects which may exist for the associated file
       
  1834  * due to variant processing / aliasing
       
  1835  */
       
  1836 
       
  1837 void TRomFile::SetRomEntry(TRomEntry* aEntry)
       
  1838 	{
       
  1839 	// Need to add to the tail of the list, for backwards compatibility
       
  1840 	// Adding to the front of the list changes the iPrimary and iSecondary
       
  1841 	// values in the TRomHeader when multiple variants are present
       
  1842 
       
  1843 	if (iFinal)
       
  1844 		return;			// address already established so no fixup required
       
  1845 	if (iRomEntry==0)
       
  1846 		{
       
  1847 		iRomEntry = aEntry;
       
  1848 		return;
       
  1849 		}
       
  1850 	TRomEntry* entry = iRomEntry;
       
  1851 	while (entry->iAddressLin != 0)
       
  1852 		entry = (TRomEntry*)entry->iAddressLin;
       
  1853 	entry->iAddressLin = (TLinAddr)aEntry;
       
  1854 	}
       
  1855 
       
  1856 void TRomBuilderEntry::FixupRomEntries(TInt aSize)
       
  1857 	{
       
  1858 	if (iPatched)
       
  1859 		return;		// patched files don't appear in the ROM file system
       
  1860 
       
  1861 	iRomNode->Finalise(aSize);
       
  1862 	}
       
  1863 
       
  1864 /**
       
  1865  * TRomNode::Finalise updates the associated TRomEntry objects with the final size and
       
  1866  * linear address information supplied by the TRomBuilderEntry. It also stores the
       
  1867  * summary information for resolving static linkages to this executable (if appropriate)
       
  1868  * and adjusts the TRomNodes so that they are identical to the ones which would be 
       
  1869  * obtained by walking the directory structure in an existing ROM.
       
  1870  */
       
  1871 void TRomNode::Finalise(TInt aSize)
       
  1872 	{
       
  1873 	TRACE(TIMPORT,Print(ELog,"TRomNode %s Finalise %08x %d\n", (const char*)TModuleName(*this), iRomFile->iFinal));
       
  1874 	iRomFile->Finalise(aSize);
       
  1875 	}
       
  1876 
       
  1877 /**
       
  1878  * TRomFile::Finalise updates the associated TRomEntry objects with the final size and
       
  1879  * linear address information supplied by the TRomBuilderEntry. It also stores the
       
  1880  * summary information for resolving static linkages to this executable (if appropriate)
       
  1881  * and adjusts the TRomFiles so that they are identical to the ones which would be 
       
  1882  * obtained by walking the directory structure in an existing ROM.
       
  1883  */
       
  1884 void TRomFile::Finalise(TInt aSize)
       
  1885 	{
       
  1886 	if (iFinal)
       
  1887 		return;
       
  1888 	TLinAddr ra = iRbEntry->iHeaderRange.iImageAddr;
       
  1889 	TRomEntry* entry = iRomEntry;
       
  1890 	while (entry)
       
  1891 		{
       
  1892 		TRomEntry* next = (TRomEntry*)entry->iAddressLin;
       
  1893 		entry->iSize = aSize;
       
  1894 		entry->iAddressLin = ra;
       
  1895 		entry = next;
       
  1896 		}
       
  1897 	iAddresses = iRbEntry->iHeaderRange;
       
  1898 	iAddresses.iSize = aSize;
       
  1899 	if ((!iRbEntry->iResource) && (!iRbEntry->HCRDataFile()))
       
  1900 		{
       
  1901 		iExportDir = iAddresses;
       
  1902 		iExportDir.iSize = iRbEntry->iHdr->iExportDirCount * sizeof(TLinAddr);
       
  1903 		iExportDir.Move(RomImgHdr()->iExportDir - iAddresses.iRunAddr);
       
  1904 		}
       
  1905 	iRbEntry = 0;
       
  1906 	iFinal = ETrue;
       
  1907 	}
       
  1908 
       
  1909 void TRomBuilderEntry::SetRomNode(TRomNode* aNode)
       
  1910 	{
       
  1911 	iRomNode = aNode;
       
  1912 	}
       
  1913 
       
  1914 
       
  1915 void TImageSection::Load() const
       
  1916 	{ 
       
  1917 	if (iSize && iImagePtr && iFilePtr) 
       
  1918 		memcpy(iImagePtr,iFilePtr,iSize); 
       
  1919 	}
       
  1920 
       
  1921 /**
       
  1922  * TDllExportInfo is the information about a DLL which is necessary to
       
  1923  * resolve a static link to that DLL. It all comes from the TRomImageHeader,
       
  1924  * as it would with a static linkage resolved at runtime.
       
  1925  */
       
  1926 TRomFile::TRomFile()
       
  1927 	{
       
  1928 	memset(this, 0, sizeof(TRomFile));
       
  1929 	iRefCount = 1;
       
  1930 	iHwvd = KVariantIndependent;
       
  1931 	iDataBssOffsetInExe = -1;
       
  1932 	}
       
  1933 
       
  1934 TRomFile::~TRomFile()
       
  1935 	{
       
  1936 	delete[] iDeps;
       
  1937 	delete[] iPDeps;
       
  1938 	}
       
  1939 
       
  1940 TInt TRomFile::AddressFromOrdinal(TLinAddr& aEDataAddr, TLinAddr& aExport, TUint aOrdinal)
       
  1941 //
       
  1942 // Get the export address of symbol aOrdinal
       
  1943 //
       
  1944 	{
       
  1945 	if(aOrdinal == 0)
       
  1946 	{
       
  1947 		aEDataAddr = iExportDir.iRunAddr -1 ;
       
  1948 		aExport = *(TLinAddr*)((TLinAddr*)iExportDir.iImagePtr - 1);
       
  1949 		if((TInt)aExport == ExportDirCount()) {
       
  1950 			aEDataAddr = 0;
       
  1951 			aExport = 0;
       
  1952 		}
       
  1953 		return KErrNone;
       
  1954 	}
       
  1955 	
       
  1956 	TUint index = aOrdinal - KOrdinalBase;
       
  1957 	if (index >= (TUint)ExportDirCount())
       
  1958 		return KErrNotFound;
       
  1959 	aEDataAddr = iExportDir.iRunAddr + index * sizeof(TLinAddr);
       
  1960 	aExport = ((TLinAddr*)iExportDir.iImagePtr)[index];
       
  1961 	return KErrNone;
       
  1962 	}
       
  1963 
       
  1964 
       
  1965 bool TRomFile::ComputeSmpSafe(const TRomBuilderEntry* aRbEntry)
       
  1966 	{
       
  1967 	// A component is SMP safe if:
       
  1968 	//
       
  1969 	// 1. It's E32 image file is marked as SMP safe (MMP keyword SMPSAFE).
       
  1970 	// 2. All components it links to are SMP safe.
       
  1971 	//
       
  1972 	// This implies a recursive dependency structure.
       
  1973 
       
  1974 	if (iSmpInfo.isInit)
       
  1975 		{
       
  1976 		// We have already visited this node.
       
  1977 		return iSmpInfo.isSafe;
       
  1978 		}
       
  1979 
       
  1980 	// Mark this node as "active," meaning that we are currently evaluating it. We
       
  1981 	// use this to detect cycles in the dependency graph.
       
  1982 	iSmpInfo.isActive = 1;
       
  1983 
       
  1984 	iSmpInfo.isSafe = 1;
       
  1985 
       
  1986 	// Have we found any cycle in the graph?
       
  1987 	bool is_cycle = 0;
       
  1988 
       
  1989 	if ( aRbEntry->iOrigHdr->iFlags & KImageSMPSafe )
       
  1990 		{
       
  1991 		// OK, the E32 file for this node is marked as SMPSAFE. Now we need to check
       
  1992 		// that all nodes we depend on are SMP safe.
       
  1993 
       
  1994 		for (int i = 0; i < iNumDeps; i++)
       
  1995 			{
       
  1996 			TRomFile* e = iDeps[i];
       
  1997 
       
  1998 			assert(this != e);
       
  1999 
       
  2000 			if (e->iSmpInfo.isActive)
       
  2001 				{
       
  2002 				is_cycle = 1;
       
  2003 				}
       
  2004 			else if ( ! e->ComputeSmpSafe(e->iRbEntry) )
       
  2005 				{
       
  2006 				if (gLogLevel & LOG_LEVEL_SMP_INFO)
       
  2007 					{
       
  2008 					Print(ELog,"SMP-unsafe: %s: links to unsafe component %s.\n",
       
  2009 							aRbEntry->iBareName , e->iRbEntry->iBareName);
       
  2010 					}
       
  2011 
       
  2012 				iSmpInfo.isSafe = 0;
       
  2013 				break;
       
  2014 				}
       
  2015 			}
       
  2016 		}
       
  2017 	else
       
  2018 		{
       
  2019 		if (gLogLevel & LOG_LEVEL_SMP_INFO)
       
  2020 			{
       
  2021 			Print(ELog,"SMP-unsafe: %s: MMP keyword SMPSAFE not used.\n", aRbEntry->iBareName);
       
  2022 			}
       
  2023 
       
  2024 		iSmpInfo.isSafe = 0;
       
  2025 		}
       
  2026 
       
  2027 	iSmpInfo.isActive = 0;
       
  2028 
       
  2029 	if (!iSmpInfo.isSafe || !is_cycle)
       
  2030 		{
       
  2031 		iSmpInfo.isInit = 1;
       
  2032 		}
       
  2033 
       
  2034 	return iSmpInfo.isSafe;
       
  2035 	}
       
  2036 
       
  2037 /**
       
  2038  * TRomNode::CopyDirectory performs a deep copy of the TRomNode structure
       
  2039  */
       
  2040 TRomNode* TRomNode::CopyDirectory(TRomNode*& aLastExecutable, TRomNode* aParent)
       
  2041 	{
       
  2042 	if (iHidden && iChild==0)
       
  2043 		{
       
  2044 		// Hidden file - do not copy (as it wouldn't be visible in the ROM filestructure)
       
  2045 		if (iSibling)
       
  2046 			return iSibling->CopyDirectory(aLastExecutable, aParent);
       
  2047 		else
       
  2048 			return 0;
       
  2049 		}
       
  2050 
       
  2051 	TRomNode* copy = new TRomNode(*this);
       
  2052 	copy->iParent = aParent;
       
  2053 	if(aLastExecutable==0)
       
  2054 		aLastExecutable = copy;		// this must be the root of the structure
       
  2055 
       
  2056 	// recursively copy the sub-structures
       
  2057 	if (iChild)
       
  2058 		copy->iChild = iChild->CopyDirectory(aLastExecutable, copy);
       
  2059 	if (iSibling)
       
  2060 		copy->iSibling = iSibling->CopyDirectory(aLastExecutable, aParent);
       
  2061 
       
  2062 	if (copy->iAtt & KEntryAttXIP)
       
  2063 		AddExecutableFile(aLastExecutable,copy);
       
  2064 	return copy;
       
  2065 	}
       
  2066 
       
  2067 TInt TRomNode::Alias(TRomNode* aNode, TRomNode*& aLastExecutable)
       
  2068 	{
       
  2069 	if (aNode->iAtt & KEntryAttXIP)
       
  2070 		AddExecutableFile(aLastExecutable,this);
       
  2071 	return SetBareName();
       
  2072 	}
       
  2073 
       
  2074 TInt TRomNode::Rename(TRomNode *aOldParent, TRomNode* aNewParent, TText* aNewName)
       
  2075 	{
       
  2076 	aOldParent->Remove(this);
       
  2077 	aNewParent->Add(this);
       
  2078 	free(iName);
       
  2079 	iName = (TText*)NormaliseFileName((const char*)aNewName);
       
  2080 	return SetBareName();
       
  2081 	}
       
  2082 
       
  2083 TInt TRomNode::SetBareName()
       
  2084 	{
       
  2085 	free(iBareName);
       
  2086 	TUint32 uid;
       
  2087 	TUint32 vin;
       
  2088 	TUint32 flg;
       
  2089 	iBareName = SplitFileName((const char*)iName, uid, vin, flg);
       
  2090 	if (uid || (flg & EUidPresent))
       
  2091 		return KErrBadName;
       
  2092 	if (strchr(iBareName, '{') || strchr(iBareName, '}'))
       
  2093 		return KErrBadName;
       
  2094 	if ((iAtt & KEntryAttXIP) && (flg & EVerPresent))
       
  2095 		{
       
  2096 		TUint32 ver = iRomFile->ModuleVersion();
       
  2097 		if (ver != vin)
       
  2098 			return KErrArgument;
       
  2099 		}
       
  2100 	return KErrNone;
       
  2101 	}