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