imgtools/romtools/rombuild/r_build.cpp
changeset 590 360bd6b35136
parent 0 044383f39525
child 626 ac03b93ca9c4
--- a/imgtools/romtools/rombuild/r_build.cpp	Wed Jun 16 16:51:40 2010 +0300
+++ b/imgtools/romtools/rombuild/r_build.cpp	Wed Jun 23 16:56:47 2010 +0800
@@ -1,2101 +1,1809 @@
-/*
-* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: 
-*
-*/
-
-
-#define __REFERENCE_CAPABILITY_NAMES__
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <e32std.h>
-#include <e32std_private.h>
-#include <e32rom.h>
-#include "u32std.h"
-#include <e32uid.h>
-#include <f32file.h>
-#include "h_utl.h"
-
-#define USE_IAT_FOR_IMPORTS (iOverrideFlags&KOverrideKeepIAT || (iHdr->iCpuIdentifier & 0x1000))
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
-#include <iomanip>
-#else //!__MSVCDOTNET__
-#include <iomanip.h>
-#endif
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
-#include <iomanip>
-#else //!__MSVCDOTNET__
-#include <iomanip.h>
-#endif
-
-#include "r_obey.h"
-#include "r_global.h"
-#include "r_dir.h"
-
-TInt NumRootDirs;
-
-inline TLinAddr ActualToRomAddress(TAny* anAddr)
-	{ return TLinAddr(anAddr)-TheRomMem+TheRomLinearAddress; }
-
-TBool THardwareVariant::MutuallyExclusive(THardwareVariant a) const
-	{
-	if (Layer()<=3 || a.Layer()<=3)
-		return EFalse;
-	if (Parent()==3 && a.Parent()==3)
-		return(Layer()!=a.Layer());
-	if (Parent()==3 && a.Parent()!=Layer())
-		return ETrue;
-	if (a.Parent()==3 && Parent()!=a.Layer())
-		return ETrue;
-	if (Layer()!=a.Layer())
-		return ETrue;
-	return((VMask()&a.VMask())==0);
-	}
-
-TBool THardwareVariant::IsVariant() const
-	{
-	if (Layer()<=3 || Parent()==3)
-		return EFalse;
-	TUint v=VMask();
-	TInt i;
-	for (i=0; i<16; i++)
-		{
-		if (v==TUint(1<<i))
-			return ETrue;
-		}
-	return EFalse;
-	}
-
-TInt THardwareVariant::Compare(THardwareVariant a) const
-	{
-	TUint l1=Layer();
-	TUint p1=Parent();
-	TUint v1=VMask();
-	TUint l2=a.Layer();
-	TUint p2=a.Parent();
-	TUint v2=a.VMask();
-
-	if (l1<=3)
-		{
-		if (l2<=3)
-			{
-			return EEqual;
-			}
-		return EGreater;
-		}
-	if (l2<=3)
-		return ELess;
-	if (p1==3)
-		{
-		if (p2==3)
-			{
-			if (l1==l2)
-				return EEqual;
-			return EUnordered;
-			}
-		if (p2==l1)
-			return EGreater;
-		return EUnordered;
-		}
-	if (p2==3)
-		{
-		if (p1==l2)
-			return ELess;
-		return EUnordered;
-		}
-	if (l1!=l2)
-		return EUnordered;
-	if ((v1&v2)==v1)
-		return ELess;
-	if ((v1&v2)==v2)
-		return EGreater;
-	return EUnordered;
-	}
-//
-TInt TRomNode::Count=0;
-TRomNode::TRomNode(const TText* aName, TRomBuilderEntry* aEntry)
-//
-// Constructor from TRomBuilderEntry, i.e. for new file or directory
-//
-	{
-	memset(this, 0, sizeof(TRomNode));
-	iAtt = (TUint8)KEntryAttReadOnly;
-	iName = (TText*)NormaliseFileName((const char*)aName);
-	iIdentifier=TRomNode::Count++;
-	iRomFile = new TRomFile;
-	if (aEntry)
-		{
-		iRomFile->iRbEntry = aEntry;
-		aEntry->SetRomNode(this);
-		iBareName = strdup(aEntry->iBareName);
-		iRomFile->iHwvd = aEntry->iHardwareVariant;
-		}
-	else
-		{
-		iRomFile->iDir = ETrue;
-		iAtt |= (TUint8)KEntryAttDir;
-		iBareName = strdup((const char*)iName);
-		iRomFile->iHwvd = KVariantIndependent;
-		}
-	TRACE(TROMNODE,Print(ELog, "TRomNode %d name %s bare %s att %02x romfile %08x\n", iIdentifier,
-			iName, iBareName, iAtt, iRomFile));
-	}
-
-TRomNode::TRomNode(const TText* aName, TRomNode* aNode)
-//
-// Constructor from TRomNode, i.e. for aliased file
-//
-	{
-	memset(this, 0, sizeof(TRomNode));
-	iAtt = aNode->iAtt;
-	iIdentifier=TRomNode::Count++;
-	iName = (TText*)NormaliseFileName((const char*)aName);
-	iHidden = aNode->iHidden;
-	iRomFile = aNode->iRomFile;
-	if (iRomFile)
-		{
-		iRomFile->Open();
-		}
-	TRACE(TROMNODE,Print(ELog, "TRomNode %d DUP name %s romfile %08x\n", iIdentifier, iName, iRomFile));
-	}
-
-TRomNode::TRomNode(const TRomNode& aNode)
-//
-// Copy constructor - only used in deep copy function
-//
-	{
-	memset(this, 0, sizeof(TRomNode));
-	iAtt = aNode.iAtt;
-	iIdentifier=TRomNode::Count++;
-	iName = (TText*)strdup((const char*)aNode.iName);
-	iBareName = strdup(aNode.iBareName);
-	iHidden = aNode.iHidden;
-	iRomFile = aNode.iRomFile;
-	if (iRomFile)
-		{
-		iRomFile->Open();
-		}
-	TRACE(TROMNODE,Print(ELog, "TRomNode %d COPY name %s bare %s att %02x romfile %08x\n", iIdentifier,
-			iName, iBareName, iAtt, iRomFile));
-	}
-
-TRomNode::~TRomNode()
-	{
-	free(iName);
-	free(iBareName);
-	if (iRomFile)
-		iRomFile->Close();
-	}
-
-TRomNode* TRomNode::FindInDirectory(const TText* aName)
-//
-// Check if the TRomNode for aName exists in aDir, and if so, return it.
-//
-	{
-
-	TRomNode *entry=iChild; // first subdirectory or file
-	while (entry)
-		{
-		if (!entry->iHidden && (stricmp((const char *)aName, (const char *)entry->iName))==0) 
-			return entry;
-		else
-			entry=entry->iSibling;
-		}
-	return 0;
-	}
-
-TRomNode* TRomNode::FindInDirectory(const TText* aName, THardwareVariant aVariant, TBool aPatchDataFlag)
-//
-// Check for a file with same name and a compatible hardware variant
-//
-	{
-
-	TRomNode *entry=iChild; // first subdirectory or file
-	while (entry)
-		{
-		if (((!entry->iHidden)||aPatchDataFlag) && entry->iRomFile && (stricmp((const char *)aName, (const char *)entry->iName))==0) 
-			{
-			if (!aVariant.MutuallyExclusive(entry->HardwareVariant()))
-				return entry;
-			}
-		entry=entry->iSibling;
-		}
-	return 0;
-	}
-
-void TRomNode::AddFile(TRomNode* aChild)
-	{
-	if (!(iAtt & KEntryAttDir))
-		{
-		Print(EError, "Adding subdirectory to a file!!!\n");
-		return;
-		}
-	Add(aChild);
-	}
-
-TRomNode* TRomNode::NewSubDir(const TText* aName)
-	{
-	if (!(iAtt & KEntryAttDir))
-		{
-		Print(EError, "Adding subdirectory to a file!!!\n");
-		return 0;
-		}
-
-	TRomNode* node = new TRomNode(aName);
-	if (node==0)
-		{
-		Print(EError, "TRomNode::NewNode: Out of memory\n");
-		return 0;
-		}
-	Add(node);
-	return node;
-	}
-
-void TRomNode::Add(TRomNode* aChild)
-	{
-	if (iChild) // this node is a non-empty directory
-		{
-		TRomNode* dir = iChild; // find where to link in the new node
-		while (dir->iSibling)
-			dir = dir->iSibling;
-		dir->iSibling = aChild;
-		}
-	else
-		iChild = aChild; // else just set it up as the child of the dir
-	aChild->iSibling = 0;
-	aChild->iParent = this;
-	}
-
-void TRomNode::Remove(TRomNode* aChild)
-	{
-	if (iChild==0)
-		{
-		Print(EError, "Removing file from a file!!!\n");
-		return;
-		}
-	if (iChild==aChild) // first child in this directory
-		{
-		iChild = aChild->iSibling;
-		aChild->iSibling = 0;
-		aChild->iParent = 0;
-		return;
-		}
-	TRomNode* prev = iChild;
-	while (prev->iSibling && prev->iSibling != aChild)
-		prev = prev->iSibling;
-	if (prev==0)
-		{
-		Print(EError, "Attempting to remove file not in this directory!!!\n");
-		return;
-		}
-	prev->iSibling = aChild->iSibling;
-	aChild->iSibling = 0;
-	aChild->iParent = 0;
-	}
-
-void TRomNode::CountDirectory(TInt& aFileCount, TInt& aDirCount)
-	{
-	TRomNode *current=iChild;
-	while(current)
-		{
-		if (current->iChild)
-			aDirCount++;
-		else if (!current->iHidden)
-			aFileCount++;
-		current=current->iSibling;
-		}
-	}
-
-/**
- * Walk the contents of the directory, accumulating the
- * files as FileEntry objects in the specified RomFileStructure
- * and recursively handling the sub-directories
- *
- * TRomNode::ProcessDirectory is a pair with
- * RomFileStructure::ProcessDirectory
- */
-int TRomNode::ProcessDirectory(RomFileStructure* aRFS)
-	{
-	TInt r=KErrNone;
-	TRomNode *current=iChild;
-	while(current)
-		{
-		if (current->iAtt & (TUint8)KEntryAttDir)
-			{
-			r=aRFS->ProcessDirectory(current);
-			if (r!=KErrNone)
-				return r;
-			}
-		else if (!current->iHidden)
-			{
-			FileEntry *pE=FileEntry::New(current);
-			if (!pE)
-				return KErrNoMemory;
-			r=aRFS->Add(*pE);
-			if (r==KErrOverflow)
-				return r;
-			}
-		current=current->iSibling;
-		}
-	return r;
-	}
-
-void TRomNode::AddExecutableFile(TRomNode*& aLast, TRomNode* aNode)
-	{
-	aLast->iNextExecutable = aNode;
-	aLast = aNode;
-	aNode->iAtt |= KEntryAttXIP;
-	}
-
-char* TRomNode::BareName() const
-	{
-	return iBareName;
-	}
-
-TUint32 TRomNode::Uid3() const
-	{
-	return iRomFile->Uid3();
-	}
-
-TUint32 TRomNode::ModuleVersion() const
-	{
-	return iRomFile->ModuleVersion();
-	}
-
-THardwareVariant TRomNode::HardwareVariant() const
-	{
-	return iRomFile->HardwareVariant();
-	}
-
-TUint32 TRomNode::ABI() const
-	{
-	return iRomFile->ABI();
-	}
-
-TUint32 TRomFile::Uid3() const
-	{
-	assert(!iDir);
-	if (iRbEntry)
-	{
-		if(iRbEntry->iHdr)
-			return iRbEntry->iHdr->iUid3;
-	}
-	return RomImgHdr()->iUid3;
-	}
-
-TUint32 TRomFile::ModuleVersion() const
-	{
-	assert(!iDir);
-	if (iRbEntry)
-	{
-		if(iRbEntry->iHdr)
-			return iRbEntry->iHdr->ModuleVersion();
-	}
-	return RomImgHdr()->iModuleVersion;
-	}
-
-THardwareVariant TRomFile::HardwareVariant() const
-	{
-	return iHwvd;
-	}
-
-TUint32 TRomFile::ABI() const
-	{
-	assert(!iDir);
-	if (iRbEntry)
-	{
-		if(iRbEntry->iHdr)
-			return iRbEntry->iHdr->ABI();
-	}
-	return RomImgHdr()->iFlags & KRomImageABIMask;
-	}
-
-TInt TRomFile::ExportDirCount() const
-	{
-	assert(!iDir);
-	if (iRbEntry)
-	{
-		if(iRbEntry->iHdr)
-			return iRbEntry->iHdr->iExportDirCount;
-	}
-	return RomImgHdr()->iExportDirCount;
-	}
-
-TUint32 TRomFile::RomImageFlags() const
-	{
-	assert(!iDir);
-	if (iRbEntry)
-		{
-		if(iRbEntry->iHdr)
-		{
-		const TUint KRomFlagMask = KImageDll | KImageNoCallEntryPoint | KImageFixedAddressExe | KImageNmdExpData;
-		TUint romflags = iRbEntry->iHdr->iFlags & KRomFlagMask;
-		return iRbEntry->iRomImageFlags | romflags;
-		}
-		}
-	return RomImgHdr()->iFlags;
-	}
-
-TLinAddr TRomFile::DataBssLinearBase() const
-	{
-	assert(!iDir);
-	if (iRbEntry)
-		return iRbEntry->iDataBssLinearBase;
-	return RomImgHdr()->iDataBssLinearBase;
-	}
-
-const SSecurityInfo& TRomFile::SecurityInfo() const
-	{
-	assert(!iDir);
-	if (iRbEntry)
-		return iRbEntry->iS;
-	return RomImgHdr()->iS;
-	}
-
-TInt TRomNode::FullNameLength(TBool aIgnoreHiddenAttrib) const
-	{
-	TInt l = 0;
-	// aIgnoreHiddenAttrib is used to find the complete file name length as
-	// in ROM of a hidden file.
-	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
-		l = iParent->FullNameLength() + 1;
-	l += strlen((const char*)iName);
-	return l;
-	}
-
-TInt TRomNode::GetFullName(char* aBuf, TBool aIgnoreHiddenAttrib) const
-	{
-	TInt l = 0;
-	TInt nl = strlen((const char*)iName);
-	// aIgnoreHiddenAttrib is used to find the complete file name as in ROM of a hidden file.
-	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
-		l = iParent->GetFullName(aBuf);
-	char* b = aBuf + l;
-	if (l)
-		*b++ = '\\', ++l;
-	memcpy(b, iName, nl);
-	b += nl;
-	*b = 0;
-	l += nl;
-	return l;
-	}
-
-TInt CompareCapabilities(const SCapabilitySet& aSubCaps, const SCapabilitySet& aSuperCaps, const char* aSubName, const char* aSuperName)
-//
-//	Check that a aSubCaps are a subset of aSuperCaps
-//
-	{
-	if ((!gPlatSecEnforcement)&&(!gPlatSecDiagnostics))
-		return KErrNone;
-	TInt i;
-	TUint32 c = 0;
-	for (i=0; i<SCapabilitySet::ENCapW; ++i)
-		c |= (aSubCaps[i] &~ aSuperCaps[i]);
-	TInt r = c ? KErrPermissionDenied : KErrNone;
-	if (r && aSubName && aSuperName)
-		{
-		TPrintType printType;
-		if(gPlatSecEnforcement)
-			printType = EError;
-		else
-			{
-			printType = EWarning;
-			r = KErrNone;
-			}
-		char* buf = (char*)malloc(2);
-		if(!buf)
-			return KErrNoMemory;
-		TInt len = 0;
-		for(i=0; i<ECapability_Limit; i++)
-			{
-			if( (aSubCaps[i>>5] &~ aSuperCaps[i>>5]) & (1<<(i&31)) )
-				{
-				// append capability name to buf
-				const char* name = CapabilityNames[i];
-				if(!name)
-					continue;
-				if(len)
-					{
-					buf[len++] = ' ';
-					}
-				int nameLen=strlen(name);
-				buf = (char*)realloc(buf,len+nameLen+2);
-				if(!buf)
-					return KErrNoMemory;
-				memcpy(buf+len,CapabilityNames[i],nameLen);
-				len += nameLen;
-				}
-			}
-		buf[len]=0;
-		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);
-		free(buf);
-		}
-	return r;
-	}
-
-TDllFindInfo::TDllFindInfo(const char* aImportName, const TRomBuilderEntry* aEntry)
-	{
-	TUint32 flags;
-	iBareName = SplitFileName(aImportName, iUid3, iModuleVersion, flags);
-	assert(iBareName != 0);
-	iHwVariant = aEntry->iHardwareVariant.ReturnVariant(); 
-	}
-
-TDllFindInfo::~TDllFindInfo()
-	{
-	free((void*)iBareName);
-	}
-
-// Generate name as follows:
-// PC filename (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
-TModuleName::TModuleName(const TRomBuilderEntry* a)
-	{
-	TInt l = strlen(a->iFileName) + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
-	iName = (char*)malloc(l + 1);
-	assert(iName != 0);
-	sprintf(iName, "%s (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", a->iFileName, a->iHdr->iUid3,
-		a->iHardwareVariant.ReturnVariant(), a->iHdr->ModuleVersion()>>16, a->iHdr->ModuleVersion()&0x0000ffffu);
-	}
-
-// Generate name as follows:
-// Bare name (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
-TModuleName::TModuleName(const TDllFindInfo& a)
-	{
-	TInt l = strlen(a.iBareName) + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
-	iName = (char*)malloc(l + 1);
-	assert(iName != 0);
-	sprintf(iName, "%s (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", a.iBareName, a.iUid3,
-		a.iHwVariant, a.iModuleVersion>>16, a.iModuleVersion&0x0000ffffu);
-	}
-
-// Generate name as follows:
-// Name (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
-TModuleName::TModuleName(const TRomNode& a)
-	{
-	TBool xip = (a.iAtt & KEntryAttXIP);
-	TUint32 uid3 = xip ? a.Uid3() : 0;
-	TUint32 hwvd = (TUint)a.HardwareVariant();
-	TUint32 ver = xip ? a.ModuleVersion() : 0;
-	TInt l = a.FullNameLength() + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
-	iName = (char*)malloc(l + 1);
-	assert(iName != 0);
-	char* b = iName + a.GetFullName(iName);
-	sprintf(b, " (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", uid3, hwvd, ver>>16, ver&0x0000ffffu);
-	}
-
-TModuleName::TModuleName(const TRomFile& a, const TRomNode* aRootDir)
-	{
-	iName = 0;
-	if (a.iRbEntry)
-		{
-		new (this) TModuleName(a.iRbEntry);
-		return;
-		}
-	TRomNode* x = aRootDir->iNextExecutable;
-	for(; x; x=x->iNextExecutable)
-		{
-		if (x->iRomFile == &a)
-			{
-			new (this) TModuleName(*x);
-			return;
-			}
-		}
-	}
-
-TModuleName::~TModuleName()
-	{
-	free(iName);
-	}
-
-
-/**
- * TRomNode::FindImageFileByName is always called on the root TRomNode, so
- * it doesn't consider the current TRomNode, just the linked items in the
- * iNextExecutable list.
- */
-TRomNode* TRomNode::FindImageFileByName(const TDllFindInfo& aInfo, TBool aPrintDiag, TBool& aFallBack)
-	{
-	TUint r_major = aInfo.iModuleVersion >> 16;
-	TUint r_minor = aInfo.iModuleVersion & 0x0000ffffu;
-	TRomNode* fallback = NULL;
-	aFallBack = EFalse;
-	for (TRomNode* x=iNextExecutable; x!=0; x=x->iNextExecutable)
-		{
-		if (stricmp(x->BareName(), aInfo.iBareName))
-			continue;	// name doesn't match
-		if (aPrintDiag)
-			Print(ELog, "Candidate: %s ", (const char*)TModuleName(*x) );
-		if ( !(THardwareVariant(aInfo.iHwVariant) <= x->HardwareVariant()) )
-			{
-			if (aPrintDiag)
-				Print(ELog, "HWVD mismatch - requested %08x\n", aInfo.iHwVariant);
-			continue;
-			}
-		if (aInfo.iUid3 && (aInfo.iUid3 != x->Uid3()))
-			{
-			if (aPrintDiag)
-				Print(ELog, "UID3 mismatch - requested %08x\n", aInfo.iUid3);
-			continue;
-			}
-		TUint x_major = x->ModuleVersion() >> 16;
-		TUint x_minor = x->ModuleVersion() & 0x0000ffffu;
-		if ( x->ModuleVersion() == 0x00010000 && aInfo.iModuleVersion == 0 )
-			{
-			// allow requested version 0.0 to link to 1.0 with a warning
-			fallback = x;
-			}
-		if ( x_major != r_major )
-			{
-			if (aPrintDiag)
-				Print(ELog, "Major version mismatch - requested %d\n", r_major);
-			continue;
-			}
-		if ( x_minor < r_minor )
-			{
-			if (aPrintDiag)
-				Print(ELog, "??? Minor version mismatch - requested %d\n", r_minor);
-			continue;
-			}
-		if (aPrintDiag)
-			Print(ELog, "OK\n");
-		return x;
-		}
-	if (fallback)
-		{
-		aFallBack = ETrue;
-		return fallback;
-		}
-	return 0;
-	}
-
-TInt TRomNode::CheckForVersionConflicts(const TRomBuilderEntry* a)
-	{
-	TUint r_major = a->iHdr->ModuleVersion() >> 16;
-	TUint r_minor = a->iHdr->ModuleVersion() & 0x0000ffffu;
-	TInt errors = 0;
-	for (TRomNode* x=iNextExecutable; x!=0; x=x->iNextExecutable)
-		{
-		if (x->iRomFile->iRbEntry == a)
-			continue;	// don't compare a with itself
-		if (stricmp(x->BareName(), a->iBareName))
-			continue;	// name doesn't match
-		if ( a->iHardwareVariant.MutuallyExclusive(x->HardwareVariant()) )
-			continue;	// HWVDs are mutually exclusive
-		if ( a->iHdr->iUid3 && x->Uid3() && (a->iHdr->iUid3 != x->Uid3()) )
-			continue;	// UID3's don't match
-		TUint x_major = x->ModuleVersion() >> 16;
-		TUint x_minor = x->ModuleVersion() & 0x0000ffffu;
-		if (x_major == r_major && x_minor != r_minor)	// allow two copies of same file
-			{
-			Print(EError, "Version Conflict %s with %s\n", (const char*)TModuleName(a), (const char*)TModuleName(*x) );
-			++errors;
-			}
-		}
-	return errors;
-	}
-
-TInt E32Rom::WriteHeadersToRom(char *anAddr)
-//
-// Follow the TRomBuilderEntry tree, writing TRomEntry headers to the rom.
-//
-	{
-	TRACE(TTIMING,Print(EAlways,"0\n"));
-	TRACE(TDIR,Print(EAlways,"WriteHeadersToRom()\n"));
-	char* start=anAddr;
-	TRomRootDirectoryList* dirPointers=(TRomRootDirectoryList*)anAddr;
-	anAddr+=NumberOfVariants*sizeof(TRootDirInfo)+sizeof(TInt);
-	RomFileStructure* pS=RomFileStructure::New(NumberOfVariants);
-	if (!pS)
-		Print(EError,"Error creating RomFileStructure\n");
-	TInt r=pS->ProcessDirectory(iObey->iRootDirectory);
-	if (r!=KErrNone)
-		Print(EError,"Error %d processing directory tree\n",r);
-	TInt c=pS->Count();
-	NumRootDirs=c;
-	if (c!=NumberOfVariants)
-		Print(EError,"Error processing directory tree NR=%d NV=%d\n",c,NumberOfVariants);
-	dirPointers->iNumRootDirs=c;
-	TInt i;
-	TRACE(TDIR,Print(EAlways,"Count=%d\n",c));
-	TRACE(TDIR,pS->DebugPrint());
-	for(i=0; i<c; i++)
-		{
-		DirEntry* pD=(DirEntry*)&(*pS)[i];
-		TRomDir* pR=pD->CreateRomEntries(anAddr);
-		dirPointers->iRootDir[i].iHardwareVariant=TUint(pD->Variants().Lookup());
-		dirPointers->iRootDir[i].iAddressLin=ActualToRomAddress(pR);
-		}
-	TRACE(TDIR,Print(EAlways,"Beginning final cleanup\n"));
-	delete pS;
-	TRACE(TTIMING,Print(EAlways,"1\n"));
-	return anAddr-start;
-	}
-
- void TRomNode::Destroy()
-//
-// Follow the TRomNode tree, destroying it
-//
-	{
-
- 	TRomNode *current = this; // root has no siblings
-	while (current)
-		{
-		if (current->iChild)
-			current->iChild->Destroy();
-		TRomNode* prev=current;
-		current=current->iSibling;
-		delete prev;
-		}
- 	}
-
-
-TInt TRomNode::SetAtt(TText *anAttWord)
-//
-// Set the file attribute byte from the letters passed
-//
-	{
-	iAtt=0;
-	if (anAttWord==0 || anAttWord[0]=='\0')
-		return Print(EError, "Missing argument for keyword 'attrib'.\n");
-	for (TText *letter=anAttWord;*letter!=0;letter++)
-		{
-		switch (*letter)
-			{
-		case 'R':
-		case 'w':
-			iAtt |= KEntryAttReadOnly;
-			break;
-		case 'r':
-		case 'W':
-			iAtt &= ~KEntryAttReadOnly;
-			break;
-		case 'H':
-			iAtt |= KEntryAttHidden;
-			break;
-		case 'h':
-			iAtt &= ~KEntryAttHidden;
-			break;
-		case 'S':
-			iAtt |= KEntryAttSystem;
-			break;
-		case 's':
-			iAtt &= ~KEntryAttSystem;
-			break;
-		default:
-			return Print(EError, "Unrecognised attrib - '%c'.\n", *letter);
-			break;
-			}
-		}
-	return KErrNone;
-	}
-
-TRomBuilderEntry::TRomBuilderEntry(const char *aFileName,TText *aName)
-//
-// Constructor
-//
-	:
-	E32ImageFile(),
-	iName(0),
-	iResource(EFalse), iNonXIP(EFalse), iPreferred(EFalse), iCompression(0), iPatched(EFalse),iArea(0),
-	iOverrideFlags(0),iCodeAlignment(0),iDataAlignment(0),iUid1(0), iUid2(0), iUid3(0),iBareName(0), 
-	iHardwareVariant(KVariantIndependent),iDataBssOffset(0xffffffff), 
-	iStackReserve(0),iIATRefs(0), iNext(0), iNextInArea(0), 
-	iRomImageFlags(0),iProcessName(0), iRomNode(NULL)
-	{
-	if (aFileName)
-   		iFileName = NormaliseFileName((const char*)aFileName);
-	if (aName)
-		iName = (TText*)NormaliseFileName((const char*)aName);
-	}
-
-TRomBuilderEntry::~TRomBuilderEntry()
-//
-// Destructor
-//
-	{
-
-	free(iFileName);
-	iFileName = 0;
-	free(iName);
-	iName = 0;
-	delete[] iProcessName;
-	free(iBareName);
-	iBareName = 0;
-	delete[] iIATRefs;
-	}
-
-TInt isNumber(TText *aString)
-	{
-	if (aString==NULL)
-		return 0;
-	if (strlen((char *)aString)==0)
-		return 0;
-	return isdigit(aString[0]);
-	}
-
-TInt getNumber(TText *aStr)
-	{
-	TUint a;
-	#ifdef __TOOLS2__
-	istringstream val((char *)aStr);
-	#else
-	istrstream val((char *)aStr,strlen((char *)aStr));
-	#endif
-
-#if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
-	val >> setbase(0);
-#endif //__MSVCDOTNET__
-
-	val >> a;
-	return a;
-	}
-
-TInt TRomBuilderEntry::SetCodeAlignment(TText* aStr)
-	{
-    if (!aStr || (aStr && isNumber(aStr)==0))
-		return Print(EError, "Number required as argument for keyword 'code-align'.\n");
-    iCodeAlignment=getNumber(aStr);
-    return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetDataAlignment(TText* aStr)
-	{
-    if (!isNumber(aStr))
-		return Print(EError, "Number required as argument for keyword 'data-align'.\n");
-    TInt align=getNumber(aStr);
-	if (align<0 || (align&0x0F) != 0)
-		return Print(EError, "Positive multiple of 16 required for 'data-align'.\n");
-	iDataAlignment=align;
-    return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetRelocationAddress(TText *aStr)
-	{
-	if (aStr && isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'reloc'.\n");
-	iOverrideFlags |= KOverrideAddress;
-	iRelocationAddress=aStr ? getNumber(aStr) : 0xFFFFFFFF;
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetStackReserve(TText *aStr)
-	{
-	if (isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'stackreserve'.\n");
-	iOverrideFlags |= KOverrideStackReserve;
-	iStackReserve=getNumber(aStr);
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetStackSize(TText *aStr)
-	{
-	if (isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'stack'.\n");
-	iOverrideFlags |= KOverrideStack;
-	iStackSize=getNumber(aStr);
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetHeapSizeMin(TText *aStr)
-	{
-	if (isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'heapmin'.\n");
-	iOverrideFlags |= KOverrideHeapMin;
-	iHeapSizeMin=getNumber(aStr);
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetHeapSizeMax(TText *aStr)
-	{
-	if (isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'heapmax'.\n");
-	iOverrideFlags |= KOverrideHeapMax;
-	iHeapSizeMax=getNumber(aStr);
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetCapability(TText *aStr)
-	{
-	iOverrideFlags |= KOverrideCapability;
-	if (isNumber(aStr))
-		{
-		Print(EDiagnostic,"Old style numeric CAPABILTY specification ignored.\n");
-		return KErrNone;
-		}
-	return ParseCapabilitiesArg(iS.iCaps, (char*)aStr);
-	}
-
-TInt TRomBuilderEntry::SetPriority(TText *aStr)
-	{
-	if (isNumber(aStr))
-		iPriority=(TProcessPriority)getNumber(aStr);
-	else
-		{
-		char *str=(char *)aStr;
-		if (stricmp(str, "low")==0)
-			iPriority=EPriorityLow;
-		else if (strnicmp(str, "background", 4)==0)
-			iPriority=EPriorityBackground;
-		else if (strnicmp(str, "foreground", 4)==0)
-			iPriority=EPriorityForeground;
-		else if (stricmp(str, "high")==0)
-			iPriority=EPriorityHigh;
-		else if (strnicmp(str, "windowserver",3)==0)
-			iPriority=EPriorityWindowServer;
-		else if (strnicmp(str, "fileserver",4)==0)
-			iPriority=EPriorityFileServer;
-		else if (strnicmp(str, "realtimeserver",4)==0)
-			iPriority=EPriorityRealTimeServer;
-		else if (strnicmp(str, "supervisor",3)==0)
-			iPriority=EPrioritySupervisor;
-		else
-			return Print(EError, "Unrecognised priority keyword.\n");
-		}
-	if (iPriority<EPriorityLow || iPriority>EPrioritySupervisor)
-		return Print(EError, "Priority out of range.\n");
-	iOverrideFlags |= KOverridePriority;
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetUid1(TText *aStr)
-	{
-	if (isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'uid1'.\n");
-	iOverrideFlags |= KOverrideUid1;
-	iUid1=getNumber(aStr);
-	return KErrNone;
-	}
-TInt TRomBuilderEntry::SetUid2(TText *aStr)
-	{
-	if (isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'uid2'.\n");
-	iOverrideFlags |= KOverrideUid2;
-	iUid2=getNumber(aStr);
-	return KErrNone;
-	}
-TInt TRomBuilderEntry::SetUid3(TText *aStr)
-	{
-	if (isNumber(aStr)==0)
-		return Print(EError, "Number required as argument for keyword 'uid3'.\n");
-	iOverrideFlags |= KOverrideUid3;
-	iUid3=getNumber(aStr);
-	return KErrNone;
-	}
-TInt TRomBuilderEntry::SetCallEntryPoint(TBool aState)
-	{
-	if (aState)
-		iOverrideFlags|=KOverrideCallEntryPoint;
-	else
-		iOverrideFlags|=KOverrideNoCallEntryPoint;
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::SetAttachProcess(TText *aStr)
-	{
-	const char* s=(const char*)aStr;
-	TInt nd=0;
-	if (*s=='\\')
-		{
-		++s;
-		++nd;
-		}
-	TInt l=strlen(s);
-	if (l==0)
-		return KErrGeneral;
-	const char* ss=s;
-	while(*ss!=0 && *ss!='.') ++ss;
-	int ext=*ss;	// 0 if no extension
-	iProcessName=new TText[l+2+(ext?0:4)];
-	char* d=(char *)iProcessName;
-	strcpy(d+1, s);
-	if (!ext)
-		{
-		char* t=d+1+l;
-		*t++='.';
-		*t++='e';
-		*t++='x';
-		*t++='e';
-		*t++=0;
-		}
-	char* dd=d;
-	int ind=nd;
-	while(*dd)
-		{
-		while(*dd && *dd!='\\') ++dd;
-		if (*dd=='\\')
-			{
-			*dd++=0;	// change \ to NUL
-			++nd;		// count path elements
-			}
-		}
-	if (!ind && nd)
-		++nd;			// add initial \ if not present
-	*d=(char)nd;
-	return 0;
-	}
-
-TInt TRomBuilderEntry::OpenImageFile()
-	{
-	Print(ELog,"Loading E32Image file %s \n", iFileName);
-	TInt err = Open(iFileName);
-	if (err != KErrNone)
-		{
-		Print(EError,"File %s is not a valid E32Image file (error %d)\n", iFileName, err);
-		return err;
-		}
-	TUint hdrfmt = iHdr->HeaderFormat();
-	if (hdrfmt != KImageHdrFmt_V)
-		{
-		Print(EError,"%s: Can't load old format binary\n", iFileName);
-		return KErrNotSupported;
-		}
-	E32ImageHeaderV* h = iHdr;
-	
-	// Overide any settings in the image file with those in the obey file
-	if (iOverrideFlags & (KOverrideUid1|KOverrideUid2|KOverrideUid3))
-		{
-		TUint uid1 = h->iUid1;
-		TUint uid2 = h->iUid2;
-		TUint uid3 = h->iUid3;
-		if (iOverrideFlags & KOverrideUid1)
-			uid1 = iUid1;
-		if (iOverrideFlags & KOverrideUid2)
-			uid2 = iUid2;
-		if (iOverrideFlags & KOverrideUid3)
-			uid3 = iUid3;
-		SetUids(TUid::Uid(uid1), TUid::Uid(uid2), TUid::Uid(uid3));
-		}
-	if (iOverrideFlags & KOverrideStack)
-		h->iStackSize = iStackSize;
-	if (iOverrideFlags & KOverrideHeapMax)
-		h->iHeapSizeMax = iHeapSizeMax;
-	if (iOverrideFlags & KOverrideHeapMin)
-		h->iHeapSizeMin = iHeapSizeMin;
-	if (iOverrideFlags & KOverridePriority)
-		h->iProcessPriority = (TUint16)iPriority;
-	if (iOverrideFlags & KOverrideCapability)
-		h->iS.iCaps = iS.iCaps;
-	for (TInt i=0; i<SCapabilitySet::ENCapW; ++i)
-		{
-		h->iS.iCaps[i] |= gPlatSecDisabledCaps[i];
-		h->iS.iCaps[i] &= gPlatSecAllCaps[i];
-		}
-
-	if (iOverrideFlags & KOverrideCodePaged)
-		{
-		h->iFlags &= ~KImageCodeUnpaged;
-		h->iFlags |= KImageCodePaged;
-		}
-	if (iOverrideFlags & KOverrideCodeUnpaged)
-		{
-		h->iFlags |= KImageCodeUnpaged;
-		h->iFlags &= ~KImageCodePaged;
-		}
-
-	if ((TInt)h->iUid1 == KExecutableImageUidValue)
-		{
-		if (iOverrideFlags & KOverrideDataPaged)
-			{
-			h->iFlags &= ~KImageDataUnpaged;
-			h->iFlags |= KImageDataPaged;
-			}
-		if (iOverrideFlags & KOverrideDataUnpaged)
-			{
-			h->iFlags |= KImageDataUnpaged;
-			h->iFlags &= ~KImageDataPaged;
-			}
-		}
-
-	switch(gCodePagingOverride)
-		{
-	case EKernelConfigPagingPolicyNoPaging:
-		h->iFlags |= KImageCodeUnpaged;
-		h->iFlags &= ~KImageCodePaged;
-		break;
-	case EKernelConfigPagingPolicyAlwaysPage:
-		h->iFlags |= KImageCodePaged;
-		h->iFlags &= ~KImageCodeUnpaged;
-		break;
-	case EKernelConfigPagingPolicyDefaultUnpaged:
-		if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
-			h->iFlags |= KImageCodeUnpaged;
-		break;
-	case EKernelConfigPagingPolicyDefaultPaged:
-		if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
-			h->iFlags |= KImageCodePaged;
-		break;
-		}
-	switch(gDataPagingOverride)
-		{
-	case EKernelConfigPagingPolicyNoPaging:
-		h->iFlags |= KImageDataUnpaged;
-		h->iFlags &= ~KImageDataPaged;
-		break;
-	case EKernelConfigPagingPolicyAlwaysPage:
-		h->iFlags |= KImageDataPaged;
-		h->iFlags &= ~KImageDataUnpaged;
-		break;
-	case EKernelConfigPagingPolicyDefaultUnpaged:
-		if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
-			h->iFlags |= KImageDataUnpaged;
-		break;
-	case EKernelConfigPagingPolicyDefaultPaged:
-		if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
-			h->iFlags |= KImageDataPaged;
-		break;
-		}
-	
-	h->iCompressionType=KUidCompressionDeflate; // XIP images are always uncompressed
-	
-	Print(ELog,"\t\tcompression format:0x%08x \n", h->iCompressionType);
-	if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
-		Print(ELog,"\t\tgCompress:%d, gCompressionMethod: 0x%08x \n", gEnableCompress , gCompressionMethod);
-
-
-	// Check the uids
-
-	if ((TInt)h->iUid1 != KExecutableImageUidValue && (TInt)h->iUid1 != KDynamicLibraryUidValue) 
-		return Print(EError, "First Uid for %s is not KExecutableImageUid or KDynamicLibraryUid\n", iFileName);
-
-	// Set up the sizes and location of the distinct areas
-
-	iHeaderRange.iSize = sizeof(TRomImageHeader);
-
-	iCodeSection.iSize    = h->iTextSize;
-	iCodeSection.iFilePtr = iData + iOrigHdr->iCodeOffset;
-
-	TUint impfmt = h->ImportFormat();
-
-	if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
-		{
-		TInt nimports = NumberOfImports();
-		if (nimports)
-			{
-			iImportAddressTableSection.iSize    = (nimports+1)*4;
-			iImportAddressTableSection.iFilePtr = iData + iOrigHdr->iCodeOffset + iOrigHdr->iTextSize;
-			iIATRefs = new TLinAddr*[nimports+1];
-			memcpy(iIATRefs, iImportAddressTableSection.iFilePtr, (nimports+1)*sizeof(TLinAddr*));
-			}
-
-		if (h->iExportDirCount)
-			{
-			iExportDirSection.iSize    = h->iExportDirCount*4;
-			iExportDirSection.iFilePtr = iData + iOrigHdr->iExportDirOffset;
-			}
-
-		// assertion - there's no rdata between IAT and Export Directory
-		TInt rdatasize = h->iCodeSize;		// overall "readonly" size
-		rdatasize -= iCodeSection.iSize;				// text
-		rdatasize -= iImportAddressTableSection.iSize;	// IAT plus trailing 0
-		rdatasize -= iExportDirSection.iSize;			// export data
-
-		if (rdatasize != 0)
-			{
-			Print(EWarning, "Unexpected code in %s: %d bytes unexplained\n", iFileName, rdatasize);
-			// expand the code to cover text+IAT+rdata
-			iCodeSection.iSize = h->iCodeSize - iExportDirSection.iSize;
-			}
-		else
-			{
-			if (USE_IAT_FOR_IMPORTS)
-				iCodeSection.iSize += iImportAddressTableSection.iSize;	// include IAT
-			}
-		}
-	else
-		{
-		// ELF-derived images have no IAT and the export directory is included in the code section
-		iImportAddressTableSection.iSize    = 0;
-		iImportAddressTableSection.iFilePtr = NULL;
-		iExportDirSection.iSize    = 0;
-		iExportDirSection.iFilePtr = NULL;
-		}
-
-	if (h->iDataSize)
-		{
-		iDataSection.iSize    = h->iDataSize;
-		iDataSection.iFilePtr = iData + iOrigHdr->iDataOffset;
-		}
-
-	iRomNode->iRomFile->iTotalDataBss = h->iDataSize + h->iBssSize;
-	iS = h->iS;
-	if (iVersionPresentInName && iVersionInName != h->ModuleVersion())
-		{
-		Print(EError,"%s: Version in name (%d.%d) does not match version in header (%d.%d)\n", iFileName,
-			iVersionInName>>16, iVersionInName&0x0000ffffu, h->ModuleVersion()>>16, h->ModuleVersion()&0x0000ffffu);
-		return KErrGeneral;
-		}
-	return KErrNone;
-	}
-
-TInt TRomNode::NameCpy(char* aDest)
-//
-// Safely copy a file name in the rom entry
-//
-	{
-
-	if ((aDest==NULL) || (iName==NULL))
-		return 0;
-	if (Unicode)
-		{
-		const unsigned char* pSourceByte=iName;
-		unsigned char* pTargetByte=(unsigned char*)aDest;
-		for (;;)
-			{
-			const TUint sourceByte=*pSourceByte;
-			if (sourceByte==0)
-				{
-				*pTargetByte=0;
-				*(pTargetByte+1)=0;
-				break;
-				}
-			if ((sourceByte&0x80)==0)
-				{
-				*pTargetByte=(unsigned char)sourceByte;
-				++pTargetByte;
-				*pTargetByte=0;
-				++pTargetByte;
-				++pSourceByte;
-				}
-			else if ((sourceByte&0xe0)==0xc0)
-				{
-				++pSourceByte;
-				const TUint secondSourceByte=*pSourceByte;
-				if ((secondSourceByte&0xc0)!=0x80)
-					{
-					Print(EError, "Bad UTF-8 '%s'", iName);
-					exit(671);
-					}
-				*pTargetByte=(unsigned char)((secondSourceByte&0x3f)|((sourceByte&0x03)<<6));
-				++pTargetByte;
-				*pTargetByte=(unsigned char)((sourceByte>>2)&0x07);
-				++pTargetByte;
-				++pSourceByte;
-				}
-			else if ((sourceByte&0xf0)==0xe0)
-				{
-				++pSourceByte;
-				const TUint secondSourceByte=*pSourceByte;
-				if ((secondSourceByte&0xc0)!=0x80)
-					{
-					Print(EError, "Bad UTF-8 '%s'", iName);
-					exit(672);
-					}
-				++pSourceByte;
-				const TUint thirdSourceByte=*pSourceByte;
-				if ((thirdSourceByte&0xc0)!=0x80)
-					{
-					Print(EError, "Bad UTF-8 '%s'", iName);
-					exit(673);
-					}
-				*pTargetByte=(unsigned char)((thirdSourceByte&0x3f)|((secondSourceByte&0x03)<<6));
-				++pTargetByte;
-				*pTargetByte=(unsigned char)(((secondSourceByte>>2)&0x0f)|((sourceByte&0x0f)<<4));
-				++pTargetByte;
-				++pSourceByte;
-				}
-			else
-				{
-				Print(EError, "Bad UTF-8 '%s'", iName);
-				exit(674);
-				}
-			}
-		const TInt numberOfBytesInTarget=(pTargetByte-(unsigned char*)aDest); // this number excludes the trailing null-terminator
-		if (numberOfBytesInTarget%2!=0)
-			{
-			Print(EError, "Internal error");
-			exit(675);
-			}
-		return numberOfBytesInTarget/2; // returns the length of aDest (in UTF-16 characters for Unicode, not bytes)
-		}
-	strcpy(aDest,(const char*)iName);
-	return strlen((const char*)iName);
-	}
-
-TInt TRomBuilderEntry::SizeInRom()
-//
-// Approximate the required size of the file when rommed
-//
-	{
-
-	TInt size1, size2;
-	SizeInSections(size1,size2);
-	return size1+size2;
-	}
-
-void TRomBuilderEntry::LoadToRom()
-//
-//
-//
-	{
-	// Copy fixed stuff into iRomImageHeader
-	E32ImageHeaderV* h = iHdr;
-	const TUint KRomFlagMask = KImageDll | KImageNoCallEntryPoint | KImageFixedAddressExe | KImageNmdExpData | KImageDataPagingMask;
-	TUint romflags = h->iFlags & KRomFlagMask;
-	TUint abi = h->ABI();
-	TUint ept = h->EntryPointFormat();
-	TUint impfmt = h->ImportFormat();
-	romflags |= (abi | ept);
-
-	iRomImageHeader = (TRomImageHeader*)iHeaderRange.iImagePtr;
-
-	iRomImageHeader->iUid1              = h->iUid1;
-	iRomImageHeader->iUid2              = h->iUid2;
-	iRomImageHeader->iUid3              = h->iUid3;
-	iRomImageHeader->iUidChecksum       = h->iUidChecksum;
-	iRomImageHeader->iEntryPoint        = iCodeSection.iRunAddr + h->iEntryPoint;
-	iRomImageHeader->iCodeAddress       = iCodeSection.iRunAddr;
-	iRomImageHeader->iDataAddress       = iDataSection.iRunAddr;
-	iRomImageHeader->iCodeSize          = iCodeSection.iSize+iExportDirSection.iSize;
-	iRomImageHeader->iTextSize          = iCodeSection.iSize;
-	iRomImageHeader->iDataSize          = iDataSection.iSize;
-	iRomImageHeader->iBssSize           = h->iBssSize;
-	iRomImageHeader->iTotalDataSize		= iRomNode->iRomFile->iTotalDataBss;
-	iRomImageHeader->iHeapSizeMin       = h->iHeapSizeMin;
-	iRomImageHeader->iHeapSizeMax       = h->iHeapSizeMax;
-	iRomImageHeader->iStackSize         = h->iStackSize;
-	iRomImageHeader->iDllRefTable       = (TDllRefTable*)(iDllRefTableRange.iImageAddr);
-	iRomImageHeader->iExportDirCount    = h->iExportDirCount;
-	iRomImageHeader->iExportDir         = (impfmt==KImageImpFmt_ELF) ?
-											iCodeSection.iRunAddr + (h->iExportDirOffset - h->iCodeOffset)
-											: iExportDirSection.iRunAddr;
-	iRomImageHeader->iS					= h->iS;
-	iRomImageHeader->iToolsVersion		= h->iToolsVersion;
-	iRomImageHeader->iModuleVersion		= h->ModuleVersion();
-	iRomImageHeader->iFlags             = romflags | iRomImageFlags;
-	iRomImageHeader->iPriority          = h->ProcessPriority();
-	iRomImageHeader->iDataBssLinearBase = iDataBssLinearBase;
-	iRomImageHeader->iNextExtension     = 0;
-	iRomImageHeader->iHardwareVariant   = iHardwareVariant;
-	iRomImageHeader->iExceptionDescriptor = 0;
-	TUint32 xd = h->iExceptionDescriptor;
-	if ((xd & 1) && (xd != 0xffffffffu))
-		iRomImageHeader->iExceptionDescriptor = (xd & ~1) + iRomImageHeader->iCodeAddress;
-
-	if (iPreferred)
-		{
-		iRomImageHeader->iModuleVersion	&= ~0xffffu;
-		iRomImageHeader->iModuleVersion	|= 0x8000u;
-		}
-
-	// Relocate the file to reflect the new addresses
-	Relocate();
-
-	// Copy the sections
-	iCodeSection.Load();
-	iExportDirSection.Load();
-	iDataSection.Load();
-	}
-
-void TRomBuilderEntry::Relocate()
-//
-// Relocates the iData to new Code and Data addresses
-//	
-	{
-	TUint codeDelta=iRomImageHeader->iCodeAddress       - iHdr->iCodeBase;
-	TUint dataDelta=iRomImageHeader->iDataBssLinearBase - iHdr->iDataBase;
-
-	// code section (text, IAT, export directory)
-
-	if (iOrigHdr->iCodeRelocOffset)
-		RelocateSection(iData + iOrigHdr->iCodeOffset, iData + iOrigHdr->iCodeRelocOffset,
-			codeDelta, dataDelta, (char*)iCodeSection.iImagePtr, iIATRefs);
-
-	// data section 
-
-	if (iOrigHdr->iDataRelocOffset)
-		RelocateSection(iData + iOrigHdr->iDataOffset, iData + iOrigHdr->iDataRelocOffset, 
-			codeDelta, dataDelta, (char*)iDataSection.iImagePtr, iIATRefs);
-
-	// export directory (only for PE-derived files)
-	if (iExportDirSection.iSize)
-		{
-		TLinAddr* ptr=(TLinAddr*)(iData + iOrigHdr->iExportDirOffset);
-
-		TLinAddr textStart = iHdr->iCodeBase;
-		TLinAddr textFinish = textStart + iHdr->iTextSize;
-		TLinAddr dataStart = textStart + iHdr->iCodeSize;
-		TLinAddr dataFinish = dataStart + iHdr->iDataSize + iHdr->iBssSize;
-	 
-		TInt i;
-		for (i=0; i<iHdr->iExportDirCount; i++, ptr++)
-			{
-			TLinAddr data=*ptr+textStart;
-			if ((data>=textStart) && (data<textFinish))
-				*ptr=data+codeDelta; // export something from the text/rdata section
-			else if ((data>=dataStart) && (data<dataFinish))
-				*ptr=data+dataDelta; // export some data or bss item
-			else
-				{
-				Print(EWarning, "Export directory in %s: item %d -> %08x, which is not text or data!\n", iFileName, i, data);
-				*ptr=0x13;	// unlucky for some
-				}
-			}
-		}
-
-	// Replace absent exports with 0
-	TLinAddr* ptr = (TLinAddr*)(iData + iOrigHdr->iExportDirOffset);
-	TInt i;
-	for (i=0; i<iHdr->iExportDirCount; i++, ptr++)
-		{
-		if ( !( iExportBitMap[i>>3] & (1u << (i&7)) ) )
-			*ptr = 0;
-		}
-
-	// Update E32ImageHeader, in case we want to do this process again later
-
-	iHdr->iCodeBase += codeDelta;
-	iHdr->iDataBase += dataDelta;
-	}
-
-
-
-
-TInt TRomBuilderEntry::FixupImports(E32Rom& aRom)
-//
-// Modify the import stubs to point directly into the export directory of the corresponding DLLs
-// using the back pointers captured by detecting relocations referring to the Import Address Table
-// The old-style Import Address Table behaviour can be retained by specifying the "keepIAT" attribute.
-//
-	{
-	if (iHdr->iImportOffset == 0)
-		return KErrNone;	// nothing to do
-
-	
-
-	TUint impfmt = iHdr->ImportFormat();
-	TUint my_abi = iHdr->ABI();
-	TRACE(TIMPORT,Print(ELog,"%40s[%08x] flags %08x\n",iFileName,(TUint)iHardwareVariant,iHdr->iFlags));
-	const E32ImportSection* importsection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
-	TLinAddr **iatRef=iIATRefs;
-	TAddressRange iatRange = iCodeSection;
-	iatRange.Move(iHdr->iTextSize);
-	if (USE_IAT_FOR_IMPORTS)
-		{
-		if (impfmt == KImageImpFmt_ELF)
-			return Print(EError, "Can't retain IAT for %s since it never existed\n", iFileName);
-		if (iRomSectionNumber==0 && aRom.iObey->iSectionPosition!=-1)
-			return Print(EError, "Can't retain IAT for %s in first section - not yet implemented\n", iFileName);
-		Print(ELog, "%s has IAT at %08x\n", iFileName, iatRange.iRunAddr);
-		}
-	const E32ImportBlock* b = (const E32ImportBlock*)(importsection + 1);
-	TInt i = iHdr->iDllRefTableCount;
-	TInt numberOfImports=0;
-	TUint *impOrdinalP = (TUint*)iImportAddressTableSection.iFilePtr;	// points to original IAT in file
-	while (i-->0)
-		{
-		char* dllname = (char*)importsection + b->iOffsetOfDllName;
-		TDllFindInfo find_info(dllname, this);
-		TBool fallback;
-		TRomNode* romnode = aRom.FindImageFileByName(find_info, EFalse, fallback);
-		if (!romnode)
-			{
-			Print(EError, "Can't fixup imports for\n\t%s\nbecause\n\t%s\nis not in rom.\n",
-						 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
-			aRom.FindImageFileByName(find_info, ETrue, fallback);
-			return KErrGeneral;
-			}
-		TRomFile* dll=romnode->iRomFile;
-		TRACE(TIMPORT,Print(ELog,"%s importing from %s\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info)));
-		if (romnode->ABI() != my_abi)
-			{
-			Print(EWarning, "File %s links to %s with different ABI\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info));
-			}
-		TInt j;
-		numberOfImports += b->iNumberOfImports;
-		if (impfmt==KImageImpFmt_ELF)
-			impOrdinalP = (TUint*)(b->Imports());	// for ELF must look in import block
-		char* codeBase = (char*)iCodeSection.iImagePtr;
-		for (j=0; j<b->iNumberOfImports; j++)
-			{
-			TLinAddr exportAddr = 0xdeadbeef;
-			TLinAddr exporter = 0xdeadbeef;
-			TUint impOrdinal = *impOrdinalP;
-			TUint impOffset = 0;
-			if (impfmt==KImageImpFmt_ELF)
-				{
-				TUint impd = *(TUint*)(codeBase + impOrdinal);
-				impOrdinal = impd & 0xffff;
-				impOffset = impd >> 16;
-				}
-			TRACE(TIMPORT,Print(ELog,"Ordinal %d\n", impOrdinal));
-			TInt ret=dll->AddressFromOrdinal(exporter, exportAddr, impOrdinal);
-			TRACE(TIMPORT,Print(ELog,"export %08x exporter %08x\n",exportAddr,exporter));
-			if (ret!=KErrNone)
-				{
-				Print(EError, "%s wants ordinal %d from %s which only exports %d functions\n",
-					iFileName, impOrdinal, 	(const char*)TModuleName(find_info), dll->ExportDirCount());
-				exporter=0x13;	// unlucky for some...
-				exportAddr=0x13;
-				}
-			else if (exportAddr == 0 && impOrdinal != 0)
-				{
-				Print(EError, "%s wants ordinal %d from %s which is absent\n",
-					iFileName, impOrdinal, 	(const char*)TModuleName(find_info));
-				exporter=0x13;	// unlucky for some...
-				exportAddr=0x13;
-				}
-			if (USE_IAT_FOR_IMPORTS)
-				{
-				// must be PE-derived
-				*iatRef=(unsigned long*)exportAddr; //iatRange.iRunAddr;					// point into IAT ...
-				*(TLinAddr*)(iatRange.iImagePtr)=exportAddr;	// ... which has a copy of the export
-				iatRange.Move(sizeof(TLinAddr));
-				iatRef++;
-				}
-			else if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2)
-				{
-				**iatRef=exporter;	// point directly into export directory
-				iatRef++;
-				}
-			else
-				{
-				// ELF-derived
-				*(TUint*)(codeBase + *impOrdinalP) = exportAddr + impOffset;
-				}
-			impOrdinalP++;
-			}
-		b = b->NextBlock(impfmt);
-		}
-	iImportCount=numberOfImports;
-	return KErrNone;
-	}
-
-const char* KF32ProcessName="efile.exe";
-const char* KWservProcessName="ewsrv.exe";
-const char* KFbservProcessName="fbserv.exe";
-const char* KMdaSvrProcessName="mediaserverstub.exe";
-const char* KC32ProcessName="c32exe.exe";
-
-const char* TRomBuilderEntry::GetDefaultAttachProcess()
-//
-// Work out the attach process from the file extension
-//
-// Only need to handle DLLs which run in F32, WSERV, FBSERV, MEDIASVR, C32
-// F32:		FSY FXT
-// WSERV:	ANI
-// FBSERV:
-// MDASVR:	MDA
-// C32:		CSY, PRT, TSY, AGT, AGX
-//
-	{
-	const char* s=(const char*)iName;
-	TInt l=strlen(s);
-	if (l<4 || s[l-4]!='.')
-		return NULL;
-	s+=(l-3);
-	if (stricmp(s,"fsy")==0)
-		return KF32ProcessName;
-	if (stricmp(s,"fxt")==0)
-		return KF32ProcessName;
-	if (stricmp(s,"ani")==0)
-		return KWservProcessName;
-	if (stricmp(s,"mda")==0)
-		return KMdaSvrProcessName;
-	if (stricmp(s,"csy")==0)
-		return KC32ProcessName;
-	if (stricmp(s,"prt")==0)
-		return KC32ProcessName;
-	if (stricmp(s,"tsy")==0)
-		return KC32ProcessName;
-	if (stricmp(s,"agt")==0)
-		return KC32ProcessName;
-	if (stricmp(s,"agx")==0)
-		return KC32ProcessName;
-	return NULL;
-	}
-
-TInt TRomBuilderEntry::FindAttachProcess(E32Rom& aRom)
-	{
-	if (iRomImageFlags & (KRomImageFlagVariant|KRomImageFlagExtension|KRomImageFlagDevice))
-		return KErrNone;
-	const char* attp_name=(const char*)iProcessName;
-	int nd=0;
-	if (attp_name)
-		nd=*attp_name++;
-	else
-		attp_name=GetDefaultAttachProcess();
-	if (!attp_name)
-		return KErrNone;
-	TInt i;
-	TUint my_abi = iHdr->ABI();
-	TUint abi = 0;
-	if (nd)
-		{
-		// path search
-		TRomNode* rn=aRom.iObey->iRootDirectory;
-		for (; nd; --nd)
-			{
-			rn=rn->FindInDirectory((TText*)attp_name);
-			if (!rn)
-				{
-				Print(EError, "Invalid attach process name element %s\n", attp_name);
-				return KErrGeneral;
-				}
-			attp_name+=(strlen(attp_name)+1);
-			}
-		iRomNode->iRomFile->iAttachProcess=rn->iRomFile;
-		abi = iRomNode->iRomFile->iAttachProcess->ABI();
-		}
-	else
-		{
-		// filename only search
-		for (i=0; i<aRom.iObey->iNumberOfPeFiles; i++)
-			{
-			TRomBuilderEntry* e=aRom.iPeFiles[i];
-			abi = e->iHdr->ABI();
-			if (stricmp((const char*)e->iName, attp_name)==0)
-				{
-				if (iRomNode->iRomFile->iAttachProcess)
-					{
-					Print(EError, "Ambiguous attach process name %s\n", attp_name);
-					return KErrGeneral;
-					}
-				iRomNode->iRomFile->iAttachProcess=e->iRomNode->iRomFile;
-				}
-			}
-		}
-	if (abi != my_abi)
-		{
-		Print(EWarning, "File %s: Attach process has different ABI\n", (const char*)TModuleName(this));
-		}
-	return KErrNone;
-	}
-
-TInt TRomBuilderEntry::BuildDependenceGraph(E32Rom& aRom)
-//
-// Fill in the iDeps
-//
-	{
-	TBool is_kernel = ((iRomImageFlags & KRomImageFlagsKernelMask) != 0);
-	TRomNode* rn = iRomNode;
-	TRomFile* rf = rn->iRomFile;
-	TUint my_abi = iHdr->ABI();
-	TUint impfmt = iHdr->ImportFormat();
-	rf->iNumDeps = iHdr->iDllRefTableCount;
-	if (IsDll() && aRom.iObey->iMemModel!=E_MM_Flexible && aRom.iObey->iMemModel!=E_MM_Multiple && (iHdr->iDataSize!=0 || iHdr->iBssSize!=0))
-		{
-		TInt r=FindAttachProcess(aRom);
-		if (r!=KErrNone)
-			return r;
-		if (aRom.iObey->iMemModel==E_MM_Moving)
-			{
-			if (rf->iAttachProcess && !(rf->iAttachProcess->RomImageFlags() & KRomImageFlagFixedAddressExe))
-				rf->iAttachProcess=NULL;	// ignore attach process if not fixed
-			}
-		}
-	TRomFile* attp=rf->iAttachProcess;
-	if (attp)
-		++rf->iNumDeps;		// extra implicit dependence on process
-	if (rf->iNumDeps)
-		{
-		rf->iDeps=new TRomFile* [rf->iNumDeps];
-		memset(rf->iDeps, 0, rf->iNumDeps*sizeof(TRomFile*));
-		}
-
-	TInt err = KErrNone;
-	const E32ImportSection* importSection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
-	const E32ImportBlock* block = (const E32ImportBlock*)(importSection + 1);
-	TInt i;
-	for (i=0; i<iHdr->iDllRefTableCount; i++, block = block->NextBlock(impfmt), TRACE(TIMPORT,Print(ELog,"DllRef/dll done\n")) )
-		{
-		char* dllname = (char*)importSection + block->iOffsetOfDllName;
-		TDllFindInfo find_info(dllname, this);
-		TBool fallback;
-		TRomNode* romnode = aRom.FindImageFileByName(find_info, EFalse, fallback);
-		if (!romnode)
-			{
-			Print(EError, "Can't build dependence graph for\n\t%s\nbecause\n\t%s\nis not in rom.\n",
-						 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
-			aRom.FindImageFileByName(find_info, ETrue, fallback);
-			err = KErrNotFound;
-			continue;
-			}
-		if (fallback)
-			{
-			Print(EWarning, "File %s links to %s\n\twhich is not in ROM. Version 1.0 of latter used instead.\n",
-					 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
-			}
-		TRACE(TIMPORT,Print(ELog,"%s links to %s\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info)));
-		TRACE(TIMPORT,Print(ELog,"Resolves to %s\n", (const char*)TModuleName(*romnode)));
-		TBool dep_is_kernel = ((romnode->iRomFile->RomImageFlags() & KRomImageFlagsKernelMask) != 0);
-		if (dep_is_kernel != is_kernel)
-			{
-			if (is_kernel)
-				{
-				Print(EError, "Kernel side executable\n\t%s\nlinks to user side executable\n\t%s\n",
-									 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
-				}
-			else
-				{
-				Print(EError, "User side executable\n\t%s\nlinks to kernel side executable\n\t%s\n",
-									 (const char*)TModuleName(this), (const char*)TModuleName(find_info));
-				}
-			err = KErrGeneral;
-			continue;
-			}
-		// prevent the situiation which importer is primary, variant or extension, exporter is device
-		if (is_kernel && !Device() && romnode->iRomFile->iRbEntry->Device())	
-			{
-			Print(EWarning, "Kernel/variant/extension\n\t%s\nlinks to non-extension LDD/PDD\n\t%s\n",
-							(const char*)TModuleName(this), (const char*)TModuleName(find_info));
-			}
-		if (romnode->ABI() != my_abi)
-			{
-			Print(EWarning, "File %s links to %s with different ABI\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info));
-			}
-
-		rf->iDeps[i]=romnode->iRomFile;
-		const SSecurityInfo& s1 = iHdr->iS;
-		const SSecurityInfo& s2 = romnode->iRomFile->SecurityInfo();
-		TInt r = CompareCapabilities(s1.iCaps, s2.iCaps, iFileName, dllname);
-		if (r != KErrNone)
-			err = r;
-		if (romnode->iRomFile==attp)
-			attp=NULL;
-		}
-
-	if (attp)
-		rf->iDeps[rf->iNumDeps-1]=attp;
-	TRACE(TIMPORT,Print(ELog,"BuildDep done all\n"));
-	return err;
-	}
-
-TInt TRomBuilderEntry::ResolveDllRefTable(E32Rom& aRom)
-//
-// Fill in the DLLRefTable
-//
-	{
-	TRomNode* rn = iRomNode;
-	TRomFile* rf = rn->iRomFile;
-	(void)aRom;
-	if (rf->iNumPDeps==0)
-		return KErrNone;	// nothing to do
-
-	TDllRefTable* dllRefTable=(TDllRefTable*)(iDllRefTableRange.iImagePtr);
-
-	TUint16 flags=0;
-
-	dllRefTable->iFlags=flags;
-	dllRefTable->iNumberOfEntries=(TUint16)rf->iNumPDeps;
-
-	TInt err = KErrNone;
-	TInt i;
-	for (i=0; i<rf->iNumPDeps; i++)
-		{
-		dllRefTable->iEntry[i]=(TRomImageHeader*)rf->iPDeps[i]->iAddresses.iRunAddr;
-		}
-	TRACE(TIMPORT,Print(ELog,"DllRef done all\n"));
-	return err;
-	}
-
-void TRomBuilderEntry::DisplaySize(TPrintType aWhere)
-	{
-	if(gLogLevel > DEFAULT_LOG_LEVEL){
-
-		if(gLogLevel & LOG_LEVEL_FILE_DETAILS)
-		{
-			// More detailed information about file name in .
-			TBool aIgnoreHiddenAttrib = ETrue;
-			TInt aLen = iRomNode->FullNameLength(aIgnoreHiddenAttrib);
-			char * aBuf = new char[aLen+1];
-			iRomNode->GetFullName(aBuf, aIgnoreHiddenAttrib);
-			if (iPatched|iRomNode->iHidden)
-				Print(aWhere, "%s\t%d\t%s\t%s\n", iFileName, SizeInRom(), iPatched?"patched":"hidden", aBuf);
-			else
-				Print(aWhere, "%s\t%d\t%s\n", iFileName, SizeInRom(), aBuf);
-			delete[] aBuf;
-		}
-	}
-	else{
-		if (iPatched|iRomNode->iHidden)
-			Print(aWhere, "%s\t%d\t%s\n", iFileName, SizeInRom(), iPatched?"patched":"hidden");
-		else
-			Print(aWhere, "%s\t%d\n", iFileName, SizeInRom());
-	}
-	}
-
-/**
- * TRomFile iRomEntry is a linked list through the various
- * distinct TRomEntry objects which may exist for the associated file
- * due to variant processing / aliasing
- */
-
-void TRomFile::SetRomEntry(TRomEntry* aEntry)
-	{
-	// Need to add to the tail of the list, for backwards compatibility
-	// Adding to the front of the list changes the iPrimary and iSecondary
-	// values in the TRomHeader when multiple variants are present
-
-	if (iFinal)
-		return;			// address already established so no fixup required
-	if (iRomEntry==0)
-		{
-		iRomEntry = aEntry;
-		return;
-		}
-	TRomEntry* entry = iRomEntry;
-	while (entry->iAddressLin != 0)
-		entry = (TRomEntry*)entry->iAddressLin;
-	entry->iAddressLin = (TLinAddr)aEntry;
-	}
-
-void TRomBuilderEntry::FixupRomEntries(TInt aSize)
-	{
-	if (iPatched)
-		return;		// patched files don't appear in the ROM file system
-
-	iRomNode->Finalise(aSize);
-	}
-
-/**
- * TRomNode::Finalise updates the associated TRomEntry objects with the final size and
- * linear address information supplied by the TRomBuilderEntry. It also stores the
- * summary information for resolving static linkages to this executable (if appropriate)
- * and adjusts the TRomNodes so that they are identical to the ones which would be 
- * obtained by walking the directory structure in an existing ROM.
- */
-void TRomNode::Finalise(TInt aSize)
-	{
-	TRACE(TIMPORT,Print(ELog,"TRomNode %s Finalise %08x %d\n", (const char*)TModuleName(*this), iRomFile->iFinal));
-	iRomFile->Finalise(aSize);
-	}
-
-/**
- * TRomFile::Finalise updates the associated TRomEntry objects with the final size and
- * linear address information supplied by the TRomBuilderEntry. It also stores the
- * summary information for resolving static linkages to this executable (if appropriate)
- * and adjusts the TRomFiles so that they are identical to the ones which would be 
- * obtained by walking the directory structure in an existing ROM.
- */
-void TRomFile::Finalise(TInt aSize)
-	{
-	if (iFinal)
-		return;
-	TLinAddr ra = iRbEntry->iHeaderRange.iImageAddr;
-	TRomEntry* entry = iRomEntry;
-	while (entry)
-		{
-		TRomEntry* next = (TRomEntry*)entry->iAddressLin;
-		entry->iSize = aSize;
-		entry->iAddressLin = ra;
-		entry = next;
-		}
-	iAddresses = iRbEntry->iHeaderRange;
-	iAddresses.iSize = aSize;
-	if ((!iRbEntry->iResource) && (!iRbEntry->HCRDataFile()))
-		{
-		iExportDir = iAddresses;
-		iExportDir.iSize = iRbEntry->iHdr->iExportDirCount * sizeof(TLinAddr);
-		iExportDir.Move(RomImgHdr()->iExportDir - iAddresses.iRunAddr);
-		}
-	iRbEntry = 0;
-	iFinal = ETrue;
-	}
-
-void TRomBuilderEntry::SetRomNode(TRomNode* aNode)
-	{
-	iRomNode = aNode;
-	}
-
-
-void TImageSection::Load() const
-	{ 
-	if (iSize && iImagePtr && iFilePtr) 
-		memcpy(iImagePtr,iFilePtr,iSize); 
-	}
-
-/**
- * TDllExportInfo is the information about a DLL which is necessary to
- * resolve a static link to that DLL. It all comes from the TRomImageHeader,
- * as it would with a static linkage resolved at runtime.
- */
-TRomFile::TRomFile()
-	{
-	memset(this, 0, sizeof(TRomFile));
-	iRefCount = 1;
-	iHwvd = KVariantIndependent;
-	iDataBssOffsetInExe = -1;
-	}
-
-TRomFile::~TRomFile()
-	{
-	delete[] iDeps;
-	delete[] iPDeps;
-	}
-
-TInt TRomFile::AddressFromOrdinal(TLinAddr& aEDataAddr, TLinAddr& aExport, TUint aOrdinal)
-//
-// Get the export address of symbol aOrdinal
-//
-	{
-	if(aOrdinal == 0)
-	{
-		aEDataAddr = iExportDir.iRunAddr -1 ;
-		aExport = *(TLinAddr*)((TLinAddr*)iExportDir.iImagePtr - 1);
-		if((TInt)aExport == ExportDirCount()) {
-			aEDataAddr = 0;
-			aExport = 0;
-		}
-		return KErrNone;
-	}
-	
-	TUint index = aOrdinal - KOrdinalBase;
-	if (index >= (TUint)ExportDirCount())
-		return KErrNotFound;
-	aEDataAddr = iExportDir.iRunAddr + index * sizeof(TLinAddr);
-	aExport = ((TLinAddr*)iExportDir.iImagePtr)[index];
-	return KErrNone;
-	}
-
-
-bool TRomFile::ComputeSmpSafe(const TRomBuilderEntry* aRbEntry)
-	{
-	// A component is SMP safe if:
-	//
-	// 1. It's E32 image file is marked as SMP safe (MMP keyword SMPSAFE).
-	// 2. All components it links to are SMP safe.
-	//
-	// This implies a recursive dependency structure.
-
-	if (iSmpInfo.isInit)
-		{
-		// We have already visited this node.
-		return iSmpInfo.isSafe;
-		}
-
-	// Mark this node as "active," meaning that we are currently evaluating it. We
-	// use this to detect cycles in the dependency graph.
-	iSmpInfo.isActive = 1;
-
-	iSmpInfo.isSafe = 1;
-
-	// Have we found any cycle in the graph?
-	bool is_cycle = 0;
-
-	if ( aRbEntry->iOrigHdr->iFlags & KImageSMPSafe )
-		{
-		// OK, the E32 file for this node is marked as SMPSAFE. Now we need to check
-		// that all nodes we depend on are SMP safe.
-
-		for (int i = 0; i < iNumDeps; i++)
-			{
-			TRomFile* e = iDeps[i];
-
-			assert(this != e);
-
-			if (e->iSmpInfo.isActive)
-				{
-				is_cycle = 1;
-				}
-			else if ( ! e->ComputeSmpSafe(e->iRbEntry) )
-				{
-				if (gLogLevel & LOG_LEVEL_SMP_INFO)
-					{
-					Print(ELog,"SMP-unsafe: %s: links to unsafe component %s.\n",
-							aRbEntry->iBareName , e->iRbEntry->iBareName);
-					}
-
-				iSmpInfo.isSafe = 0;
-				break;
-				}
-			}
-		}
-	else
-		{
-		if (gLogLevel & LOG_LEVEL_SMP_INFO)
-			{
-			Print(ELog,"SMP-unsafe: %s: MMP keyword SMPSAFE not used.\n", aRbEntry->iBareName);
-			}
-
-		iSmpInfo.isSafe = 0;
-		}
-
-	iSmpInfo.isActive = 0;
-
-	if (!iSmpInfo.isSafe || !is_cycle)
-		{
-		iSmpInfo.isInit = 1;
-		}
-
-	return iSmpInfo.isSafe;
-	}
-
-/**
- * TRomNode::CopyDirectory performs a deep copy of the TRomNode structure
- */
-TRomNode* TRomNode::CopyDirectory(TRomNode*& aLastExecutable, TRomNode* aParent)
-	{
-	if (iHidden && iChild==0)
-		{
-		// Hidden file - do not copy (as it wouldn't be visible in the ROM filestructure)
-		if (iSibling)
-			return iSibling->CopyDirectory(aLastExecutable, aParent);
-		else
-			return 0;
-		}
-
-	TRomNode* copy = new TRomNode(*this);
-	copy->iParent = aParent;
-	if(aLastExecutable==0)
-		aLastExecutable = copy;		// this must be the root of the structure
-
-	// recursively copy the sub-structures
-	if (iChild)
-		copy->iChild = iChild->CopyDirectory(aLastExecutable, copy);
-	if (iSibling)
-		copy->iSibling = iSibling->CopyDirectory(aLastExecutable, aParent);
-
-	if (copy->iAtt & KEntryAttXIP)
-		AddExecutableFile(aLastExecutable,copy);
-	return copy;
-	}
-
-TInt TRomNode::Alias(TRomNode* aNode, TRomNode*& aLastExecutable)
-	{
-	if (aNode->iAtt & KEntryAttXIP)
-		AddExecutableFile(aLastExecutable,this);
-	return SetBareName();
-	}
-
-TInt TRomNode::Rename(TRomNode *aOldParent, TRomNode* aNewParent, TText* aNewName)
-	{
-	aOldParent->Remove(this);
-	aNewParent->Add(this);
-	free(iName);
-	iName = (TText*)NormaliseFileName((const char*)aNewName);
-	return SetBareName();
-	}
-
-TInt TRomNode::SetBareName()
-	{
-	free(iBareName);
-	TUint32 uid;
-	TUint32 vin;
-	TUint32 flg;
-	iBareName = SplitFileName((const char*)iName, uid, vin, flg);
-	if (uid || (flg & EUidPresent))
-		return KErrBadName;
-	if (strchr(iBareName, '{') || strchr(iBareName, '}'))
-		return KErrBadName;
-	if ((iAtt & KEntryAttXIP) && (flg & EVerPresent))
-		{
-		TUint32 ver = iRomFile->ModuleVersion();
-		if (ver != vin)
-			return KErrArgument;
-		}
-	return KErrNone;
-	}
+/*
+* Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#define __REFERENCE_CAPABILITY_NAMES__
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <e32std.h>
+#include <e32std_private.h>
+#include <e32rom.h>
+#include "u32std.h"
+#include <e32uid.h>
+#include <f32file.h>
+#include "h_utl.h"
+
+#define USE_IAT_FOR_IMPORTS (iOverrideFlags&KOverrideKeepIAT || (iHdr->iCpuIdentifier & 0x1000))
+
+#include <iomanip> 
+#include "r_obey.h"
+#include "r_global.h"
+#include "r_dir.h"
+
+TInt NumRootDirs;
+
+inline TLinAddr ActualToRomAddress(TAny* anAddr) { 
+	return TLinAddr(anAddr)-TheRomMem+TheRomLinearAddress; 
+}
+
+TBool THardwareVariant::MutuallyExclusive(THardwareVariant a) const {
+	if (Layer()<=3 || a.Layer()<=3)
+		return EFalse;
+	if (Parent()==3 && a.Parent()==3)
+		return(Layer()!=a.Layer());
+	if (Parent()==3 && a.Parent()!=Layer())
+		return ETrue;
+	if (a.Parent()==3 && Parent()!=a.Layer())
+		return ETrue;
+	if (Layer()!=a.Layer())
+		return ETrue;
+	return((VMask()&a.VMask())==0);
+}
+
+TBool THardwareVariant::IsVariant() const {
+	if (Layer()<=3 || Parent()==3)
+		return EFalse;
+	TUint v=VMask();
+	TInt i;
+	for (i=0; i<16; i++) {
+		if (v==TUint(1<<i))
+			return ETrue;
+	}
+	return EFalse;
+}
+
+TInt THardwareVariant::Compare(THardwareVariant a) const {
+	TUint l1=Layer();
+	TUint p1=Parent();
+	TUint v1=VMask();
+	TUint l2=a.Layer();
+	TUint p2=a.Parent();
+	TUint v2=a.VMask();
+
+	if (l1<=3) {
+		if (l2<=3) {
+			return EEqual;
+		}
+		return EGreater;
+	}
+	if (l2<=3)
+		return ELess;
+	if (p1==3) {
+		if (p2==3) {
+			if (l1==l2)
+				return EEqual;
+			return EUnordered;
+		}
+		if (p2==l1)
+			return EGreater;
+		return EUnordered;
+	}
+	if (p2==3) {
+		if (p1==l2)
+			return ELess;
+		return EUnordered;
+	}
+	if (l1!=l2)
+		return EUnordered;
+	if ((v1&v2)==v1)
+		return ELess;
+	if ((v1&v2)==v2)
+		return EGreater;
+	return EUnordered;
+}
+//
+TInt TRomNode::Count=0;
+
+//
+// Constructor from TRomBuilderEntry, i.e. for new file or directory
+//
+TRomNode::TRomNode(const char* aName, TRomBuilderEntry* aEntry) {
+	memset(this, 0, sizeof(TRomNode));
+	iAtt = (TUint8)KEntryAttReadOnly;
+	iName = NormaliseFileName(aName);
+	iIdentifier=TRomNode::Count++;
+	iRomFile = new TRomFile;
+
+	if (aEntry) {
+		iRomFile->iRbEntry = aEntry;
+		aEntry->SetRomNode(this);
+		size_t len = strlen(aEntry->iBareName) + 1;
+		iBareName = new char[len];
+		memcpy(iBareName,aEntry->iBareName,len);
+		iRomFile->iHwvd = aEntry->iHardwareVariant;
+	}
+	else {
+		iRomFile->iDir = ETrue;
+		iAtt |= (TUint8)KEntryAttDir;
+		size_t len = strlen(iName) + 1;
+		iBareName = new char[len];
+		memcpy(iBareName,iName,len);
+		iRomFile->iHwvd = KVariantIndependent;
+	}
+	TRACE(TROMNODE,Print(ELog, "TRomNode %d name %s bare %s att %02x romfile %08x\n", iIdentifier,
+		iName, iBareName, iAtt, iRomFile));
+}
+
+//
+// Constructor from TRomNode, i.e. for aliased file
+//	
+TRomNode::TRomNode(const char* aName, TRomNode* aNode){
+	memset(this, 0, sizeof(TRomNode));
+	iAtt = aNode->iAtt;
+	iIdentifier=TRomNode::Count++;
+	iName = NormaliseFileName(aName);
+	iHidden = aNode->iHidden;
+	iRomFile = aNode->iRomFile;
+	if (iRomFile) {
+		iRomFile->Open();
+	}
+	TRACE(TROMNODE,Print(ELog, "TRomNode %d DUP name %s romfile %08x\n", iIdentifier, iName, iRomFile));
+}
+//
+// Copy constructor - only used in deep copy function
+//
+TRomNode::TRomNode(const TRomNode& aNode) {
+	memset(this, 0, sizeof(TRomNode));
+	iAtt = aNode.iAtt;
+	iIdentifier=TRomNode::Count++;
+	size_t len = strlen(aNode.iName) + 1;
+	iName = new char[len];
+	memcpy(iName,aNode.iName,len);
+	len = strlen(aNode.iBareName) + 1;
+	iBareName = new char[len];
+	memcpy(iBareName,aNode.iBareName,len);
+	iHidden = aNode.iHidden;
+	iRomFile = aNode.iRomFile;
+	if (iRomFile) {
+		iRomFile->Open();
+	}
+	TRACE(TROMNODE,Print(ELog, "TRomNode %d COPY name %s bare %s att %02x romfile %08x\n", iIdentifier,
+		iName, iBareName, iAtt, iRomFile));
+}
+
+TRomNode::~TRomNode() {
+	if(iName) {
+		delete []iName;
+		iName = 0 ;
+	}
+	if(iBareName){
+		delete []iBareName;
+		iBareName = 0 ;
+	}
+	if (iRomFile)
+		iRomFile->Close();
+}
+//
+// Check if the TRomNode for aName exists in aDir, and if so, return it.
+//
+TRomNode* TRomNode::FindInDirectory(const char* aName) {
+
+	TRomNode *entry=iChild; // first subdirectory or file
+	while (entry){
+		if (!entry->iHidden && (stricmp(aName, entry->iName))==0) 
+			return entry;
+		else
+			entry=entry->iSibling;
+	}
+	return 0;
+}
+//
+// Check for a file with same name and a compatible hardware variant
+//
+TRomNode* TRomNode::FindInDirectory(const char* aName, THardwareVariant aVariant, TBool aPatchDataFlag) {
+	TRomNode *entry=iChild; // first subdirectory or file
+	while (entry) {
+		if (((!entry->iHidden)||aPatchDataFlag) && entry->iRomFile && 
+			(stricmp(aName, entry->iName))==0) 	{
+				if (!aVariant.MutuallyExclusive(entry->HardwareVariant()))
+					return entry;
+		}
+		entry=entry->iSibling;
+	}
+	return 0;
+}
+
+void TRomNode::AddFile(TRomNode* aChild) {
+	if (!(iAtt & KEntryAttDir)) {
+		Print(EError, "Adding subdirectory to a file!!!\n");
+		return;
+	}
+	Add(aChild);
+}
+
+TRomNode* TRomNode::NewSubDir(const char* aName) {
+	if (!(iAtt & KEntryAttDir)) {
+		Print(EError, "Adding subdirectory to a file!!!\n");
+		return 0;
+	}
+
+	TRomNode* node = new TRomNode(aName);
+	if (node==0) {
+		Print(EError, "TRomNode::NewNode: Out of memory\n");
+		return 0;
+	}
+	Add(node);
+	return node;
+}
+
+void TRomNode::Add(TRomNode* aChild) {
+	if (iChild) {// this node is a non-empty directory 
+		TRomNode* dir = iChild; // find where to link in the new node
+		while (dir->iSibling) 
+			dir = dir->iSibling;
+		dir->iSibling = aChild;
+	}
+	else
+		iChild = aChild; // else just set it up as the child of the dir
+	aChild->iSibling = 0;
+	aChild->iParent = this;
+}
+
+void TRomNode::Remove(TRomNode* aChild) {
+	if (iChild==0) {
+		Print(EError, "Removing file from a file!!!\n");
+		return;
+	}
+	if (iChild==aChild) { // first child in this directory 
+		iChild = aChild->iSibling;
+		aChild->iSibling = 0;
+		aChild->iParent = 0;
+		return;
+	}
+	TRomNode* prev = iChild;
+	while (prev->iSibling && prev->iSibling != aChild)
+		prev = prev->iSibling;
+	if (prev==0) {
+		Print(EError, "Attempting to remove file not in this directory!!!\n");
+		return;
+	}
+	prev->iSibling = aChild->iSibling;
+	aChild->iSibling = 0;
+	aChild->iParent = 0;
+}
+
+void TRomNode::CountDirectory(TInt& aFileCount, TInt& aDirCount) {
+	TRomNode *current=iChild;
+	while(current) {
+		if (current->iChild)
+			aDirCount++;
+		else if (!current->iHidden)
+			aFileCount++;
+		current=current->iSibling;
+	}
+}
+
+/**
+* Walk the contents of the directory, accumulating the
+* files as FileEntry objects in the specified RomFileStructure
+* and recursively handling the sub-directories
+*
+* TRomNode::ProcessDirectory is a pair with
+* RomFileStructure::ProcessDirectory
+*/
+int TRomNode::ProcessDirectory(RomFileStructure* aRFS) {
+	TInt r=KErrNone;
+	TRomNode *current=iChild;
+	while(current) {
+		if (current->iAtt & (TUint8)KEntryAttDir) {
+			r=aRFS->ProcessDirectory(current);
+			if (r!=KErrNone)
+				return r;
+		}
+		else if (!current->iHidden) {
+			FileEntry *pE=FileEntry::New(current);
+			if (!pE)
+				return KErrNoMemory;
+			r=aRFS->Add(*pE);
+			if (r==KErrOverflow)
+				return r;
+		}
+		current=current->iSibling;
+	}
+	return r;
+}
+
+void TRomNode::AddExecutableFile(TRomNode*& aLast, TRomNode* aNode) {
+	aLast->iNextExecutable = aNode;
+	aLast = aNode;
+	aNode->iAtt |= KEntryAttXIP;
+}
+
+const char* TRomNode::BareName() const {
+	return iBareName  ;
+}
+
+TUint32 TRomNode::Uid3() const {
+	return iRomFile->Uid3();
+}
+
+TUint32 TRomNode::ModuleVersion() const {
+	return iRomFile->ModuleVersion();
+}
+
+THardwareVariant TRomNode::HardwareVariant() const {
+	return iRomFile->HardwareVariant();
+}
+
+TUint32 TRomNode::ABI() const {
+	return iRomFile->ABI();
+}
+
+TUint32 TRomFile::Uid3() const {
+	assert(!iDir);
+	if (iRbEntry) {
+		if(iRbEntry->iHdr)
+			return iRbEntry->iHdr->iUid3;
+	}
+	return RomImgHdr()->iUid3;
+}
+
+TUint32 TRomFile::ModuleVersion() const {
+	assert(!iDir);
+	if (iRbEntry) {
+		if(iRbEntry->iHdr)
+			return iRbEntry->iHdr->ModuleVersion();
+	}
+	return RomImgHdr()->iModuleVersion;
+}
+
+THardwareVariant TRomFile::HardwareVariant() const {
+	return iHwvd;
+}
+
+TUint32 TRomFile::ABI() const {
+	assert(!iDir);
+	if (iRbEntry) {
+		if(iRbEntry->iHdr)
+			return iRbEntry->iHdr->ABI();
+	}
+	return RomImgHdr()->iFlags & KRomImageABIMask;
+}
+
+TInt TRomFile::ExportDirCount() const {
+	assert(!iDir);
+	if (iRbEntry) {
+		if(iRbEntry->iHdr)
+			return iRbEntry->iHdr->iExportDirCount;
+	}
+	return RomImgHdr()->iExportDirCount;
+}
+
+TUint32 TRomFile::RomImageFlags() const {
+	assert(!iDir);
+	if (iRbEntry) {
+		if(iRbEntry->iHdr) {
+			const TUint KRomFlagMask = KImageDll | KImageNoCallEntryPoint | KImageFixedAddressExe | KImageNmdExpData;
+			TUint romflags = iRbEntry->iHdr->iFlags & KRomFlagMask;
+			return iRbEntry->iRomImageFlags | romflags;
+		}
+	}
+	return RomImgHdr()->iFlags;
+}
+
+TLinAddr TRomFile::DataBssLinearBase() const {
+	assert(!iDir);
+	if (iRbEntry)
+		return iRbEntry->iDataBssLinearBase;
+	return RomImgHdr()->iDataBssLinearBase;
+}
+
+const SSecurityInfo& TRomFile::SecurityInfo() const {
+	assert(!iDir);
+	if (iRbEntry)
+		return iRbEntry->iS;
+	return RomImgHdr()->iS;
+}
+
+TInt TRomNode::FullNameLength(TBool aIgnoreHiddenAttrib) const {
+	TInt l = 0;
+	// aIgnoreHiddenAttrib is used to find the complete file name length as
+	// in ROM of a hidden file.
+	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
+		l = iParent->FullNameLength() + 1;
+	l += strlen((const char*)iName);
+	return l;
+}
+
+TInt TRomNode::GetFullName(char* aBuf, TBool aIgnoreHiddenAttrib) const {
+	TInt l = 0;
+	TInt nl = strlen(iName);
+	// aIgnoreHiddenAttrib is used to find the complete file name as in ROM of a hidden file.
+	if (iParent && ( !iHidden || aIgnoreHiddenAttrib))
+		l = iParent->GetFullName(aBuf);
+	char* b = aBuf + l;
+	if (l){
+		*b++ = SLASH_CHAR; 
+		++l;
+	}
+	memcpy(b, iName, nl);
+	b += nl;
+	*b = 0;
+	l += nl;
+	return l;
+}
+
+//
+//	Check that a aSubCaps are a subset of aSuperCaps
+//
+TInt CompareCapabilities(const SCapabilitySet& aSubCaps, const SCapabilitySet& aSuperCaps, const char* aSubName, const char* aSuperName) {
+	if ((!gPlatSecEnforcement)&&(!gPlatSecDiagnostics))
+		return KErrNone;
+	TInt i;
+	TUint32 c = 0;
+	for (i=0; i<SCapabilitySet::ENCapW; ++i)
+		c |= (aSubCaps[i] &~ aSuperCaps[i]);
+	TInt r = c ? KErrPermissionDenied : KErrNone;
+	if (r && aSubName && aSuperName) {
+		TPrintType printType;
+		if(gPlatSecEnforcement)
+			printType = EError;
+		else {
+			printType = EWarning;
+			r = KErrNone;
+		}
+		char* buf = (char*)malloc(2);
+		if(!buf)
+			return KErrNoMemory;
+		TInt len = 0;
+		for(i=0; i<ECapability_Limit; i++) {
+			if( (aSubCaps[i>>5] &~ aSuperCaps[i>>5]) & (1<<(i&31)) ) {
+				// append capability name to buf
+				const char* name = CapabilityNames[i];
+				if(!name)
+					continue;
+				if(len) {
+					buf[len++] = ' ';
+				}
+				int nameLen=strlen(name);
+				buf = (char*)realloc(buf,len+nameLen+2);
+				if(!buf)
+					return KErrNoMemory;
+				memcpy(buf+len,CapabilityNames[i],nameLen);
+				len += nameLen;
+			}
+		}
+		buf[len]=0;
+		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);
+		free(buf);
+	}
+	return r;
+}
+
+TDllFindInfo::TDllFindInfo(const char* aImportName, const TRomBuilderEntry* aEntry) {
+	TUint32 flags;
+	iBareName = SplitFileName(aImportName, iUid3, iModuleVersion, flags);
+	assert(iBareName != 0);
+	iHwVariant = aEntry->iHardwareVariant.ReturnVariant(); 
+}
+
+TDllFindInfo::~TDllFindInfo() {
+	delete []iBareName;
+}
+
+// Generate name as follows:
+// PC filename (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
+TModuleName::TModuleName(const TRomBuilderEntry* a) {
+	TInt l = strlen(a->iFileName) + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
+	iName = new char[l + 1];
+	assert(iName != 0);
+	sprintf(iName, "%s (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", a->iFileName, a->iHdr->iUid3,
+		a->iHardwareVariant.ReturnVariant(), a->iHdr->ModuleVersion()>>16, a->iHdr->ModuleVersion()&0x0000ffffu);
+}
+
+// Generate name as follows:
+// Bare name (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
+TModuleName::TModuleName(const TDllFindInfo& a) {
+	TInt l = strlen(a.iBareName) + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
+	iName = new char [l + 1];
+	assert(iName != 0);
+	sprintf(iName, "%s (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", a.iBareName, a.iUid3,
+		a.iHwVariant, a.iModuleVersion>>16, a.iModuleVersion&0x0000ffffu);
+}
+
+// Generate name as follows:
+// Name (UID3:xxxxxxxx HWVD:xxxxxxxx VER:M.m)
+TModuleName::TModuleName(const TRomNode& a) {
+	TBool xip = (a.iAtt & KEntryAttXIP);
+	TUint32 uid3 = xip ? a.Uid3() : 0;
+	TUint32 hwvd = (TUint)a.HardwareVariant();
+	TUint32 ver = xip ? a.ModuleVersion() : 0;
+	TInt l = a.FullNameLength() + strlen(" (UID3:xxxxxxxx HWVD:xxxxxxxx VER:MMMMM.mmmmm)");
+	iName = new char[l + 1];
+	assert(iName != 0);
+	char* b = iName + a.GetFullName(iName);
+	sprintf(b, " (UID3:%08lx HWVD:%08lx VER:%ld.%ld)", uid3, hwvd, ver>>16, ver&0x0000ffffu);
+}
+
+TModuleName::TModuleName(const TRomFile& a, const TRomNode* aRootDir) {
+	iName = 0;
+	if (a.iRbEntry) {
+		new (this) TModuleName(a.iRbEntry);
+		return;
+	}
+	TRomNode* x = aRootDir->iNextExecutable;
+	for(; x; x=x->iNextExecutable) {
+		if (x->iRomFile == &a) {
+			new (this) TModuleName(*x);
+			return;
+		}
+	}
+}
+
+TModuleName::~TModuleName() {
+	if(iName)
+		delete []iName;
+}
+
+
+/**
+* TRomNode::FindImageFileByName is always called on the root TRomNode, so
+* it doesn't consider the current TRomNode, just the linked items in the
+* iNextExecutable list.
+*/
+TRomNode* TRomNode::FindImageFileByName(const TDllFindInfo& aInfo, TBool aPrintDiag, TBool& aFallBack) {
+	TUint r_major = aInfo.iModuleVersion >> 16;
+	TUint r_minor = aInfo.iModuleVersion & 0x0000ffffu;
+	TRomNode* fallback = NULL;
+	aFallBack = EFalse;
+	for (TRomNode* x=iNextExecutable; x!=0; x=x->iNextExecutable) {
+		if (stricmp(x->BareName(), aInfo.iBareName))
+			continue;	// name doesn't match
+		if (aPrintDiag)
+			Print(ELog, "Candidate: %s ", (const char*)TModuleName(*x) );
+		if ( !(THardwareVariant(aInfo.iHwVariant) <= x->HardwareVariant()) ) {
+			if (aPrintDiag)
+				Print(ELog, "HWVD mismatch - requested %08x\n", aInfo.iHwVariant);
+			continue;
+		}
+		if (aInfo.iUid3 && (aInfo.iUid3 != x->Uid3())) {
+			if (aPrintDiag)
+				Print(ELog, "UID3 mismatch - requested %08x\n", aInfo.iUid3);
+			continue;
+		}
+		TUint x_major = x->ModuleVersion() >> 16;
+		TUint x_minor = x->ModuleVersion() & 0x0000ffffu;
+		if ( x->ModuleVersion() == 0x00010000 && aInfo.iModuleVersion == 0 ) {
+			// allow requested version 0.0 to link to 1.0 with a warning
+			fallback = x;
+		}
+		if ( x_major != r_major ) {
+			if (aPrintDiag)
+				Print(ELog, "Major version mismatch - requested %d\n", r_major);
+			continue;
+		}
+		if ( x_minor < r_minor ) {
+			if (aPrintDiag)
+				Print(ELog, "??? Minor version mismatch - requested %d\n", r_minor);
+			continue;
+		}
+		if (aPrintDiag)
+			Print(ELog, "OK\n");
+		return x;
+	}
+	if (fallback) {
+		aFallBack = ETrue;
+		return fallback;
+	}
+	return 0;
+}
+
+TInt TRomNode::CheckForVersionConflicts(const TRomBuilderEntry* a) {
+	TUint r_major = a->iHdr->ModuleVersion() >> 16;
+	TUint r_minor = a->iHdr->ModuleVersion() & 0x0000ffffu;
+	TInt errors = 0;
+	for (TRomNode* x=iNextExecutable; x!=0; x=x->iNextExecutable) {
+		if (x->iRomFile->iRbEntry == a)
+			continue;	// don't compare a with itself
+		if (stricmp(x->BareName(), a->iBareName))
+			continue;	// name doesn't match
+		if ( a->iHardwareVariant.MutuallyExclusive(x->HardwareVariant()) )
+			continue;	// HWVDs are mutually exclusive
+		if ( a->iHdr->iUid3 && x->Uid3() && (a->iHdr->iUid3 != x->Uid3()) )
+			continue;	// UID3's don't match
+		TUint x_major = x->ModuleVersion() >> 16;
+		TUint x_minor = x->ModuleVersion() & 0x0000ffffu;
+		if (x_major == r_major && x_minor != r_minor)  {	// allow two copies of same file
+			Print(EError, "Version Conflict %s with %s\n", (const char*)TModuleName(a), (const char*)TModuleName(*x) );
+			++errors;
+		}
+	}
+	return errors;
+}
+
+//
+// Follow the TRomBuilderEntry tree, writing TRomEntry headers to the rom.
+//
+TInt E32Rom::WriteHeadersToRom(char *anAddr) {
+	TRACE(TTIMING,Print(EAlways,"0\n"));
+	TRACE(TDIR,Print(EAlways,"WriteHeadersToRom()\n"));
+	char* start=anAddr;
+	TRomRootDirectoryList* dirPointers=(TRomRootDirectoryList*)anAddr;
+	anAddr+=NumberOfVariants*sizeof(TRootDirInfo)+sizeof(TInt);
+	RomFileStructure* pS=RomFileStructure::New(NumberOfVariants);
+	if (!pS)
+		Print(EError,"Error creating RomFileStructure\n");
+	TInt r=pS->ProcessDirectory(iObey->iRootDirectory);
+	if (r!=KErrNone)
+		Print(EError,"Error %d processing directory tree\n",r);
+	TInt c=pS->Count();
+	NumRootDirs=c;
+	if (c!=NumberOfVariants)
+		Print(EError,"Error processing directory tree NR=%d NV=%d\n",c,NumberOfVariants);
+	dirPointers->iNumRootDirs=c;
+	TInt i;
+	TRACE(TDIR,Print(EAlways,"Count=%d\n",c));
+	TRACE(TDIR,pS->DebugPrint());
+	for(i=0; i<c; i++) {
+		DirEntry* pD=(DirEntry*)&(*pS)[i];
+		TRomDir* pR=pD->CreateRomEntries(anAddr);
+		dirPointers->iRootDir[i].iHardwareVariant=TUint(pD->Variants().Lookup());
+		dirPointers->iRootDir[i].iAddressLin=ActualToRomAddress(pR);
+	}
+	TRACE(TDIR,Print(EAlways,"Beginning final cleanup\n"));
+	delete pS;
+	TRACE(TTIMING,Print(EAlways,"1\n"));
+	return anAddr-start;
+}
+
+//
+// Follow the TRomNode tree, destroying it
+//
+void TRomNode::Destroy() {
+
+	TRomNode *current = this; // root has no siblings
+	while (current) {
+		if (current->iChild)
+			current->iChild->Destroy();
+		TRomNode* prev=current;
+		current=current->iSibling;
+		delete prev;
+	}
+}
+
+//
+// Set the file attribute byte from the letters passed
+//
+TInt TRomNode::SetAtt(const char* anAttWord) {
+	iAtt=0;
+	if (anAttWord==0 || anAttWord[0]=='\0')
+		return Print(EError, "Missing argument for keyword 'attrib'.\n");
+	for (const char* letter = anAttWord; *letter != 0; letter ++) {
+		switch (*letter) {
+		case 'R':
+		case 'w':
+			iAtt |= KEntryAttReadOnly;
+			break;
+		case 'r':
+		case 'W':
+			iAtt &= ~KEntryAttReadOnly;
+			break;
+		case 'H':
+			iAtt |= KEntryAttHidden;
+			break;
+		case 'h':
+			iAtt &= ~KEntryAttHidden;
+			break;
+		case 'S':
+			iAtt |= KEntryAttSystem;
+			break;
+		case 's':
+			iAtt &= ~KEntryAttSystem;
+			break;
+		default:
+			return Print(EError, "Unrecognised attrib - '%c'.\n", *letter);
+			break;
+		}
+	}
+	return KErrNone;
+}
+//
+// Constructor
+//
+TRomBuilderEntry::TRomBuilderEntry(const char *aFileName,const char* aName) :
+E32ImageFile(),
+iName(0),
+iResource(EFalse), iNonXIP(EFalse), iPreferred(EFalse), iCompression(0), iPatched(EFalse),iArea(0),
+iOverrideFlags(0),iCodeAlignment(0),iDataAlignment(0),iUid1(0), iUid2(0), iUid3(0),iBareName(0), 
+iHardwareVariant(KVariantIndependent),iDataBssOffset(0xffffffff), 
+iStackReserve(0),iIATRefs(0), iNext(0), iNextInArea(0), 
+iRomImageFlags(0),iProcessName(0), iRomNode(NULL) {
+	if (aFileName){
+		if(iFileName)
+			delete []iFileName;
+		iFileName = NormaliseFileName(aFileName);	 
+	}
+	if (aName)
+		iName = NormaliseFileName(aName);
+}
+//
+// Destructor
+//
+TRomBuilderEntry::~TRomBuilderEntry() {
+	 
+	if(iName){
+		delete []iName; 
+		iName = 0 ;
+	}
+	if(iProcessName){	
+		delete []iProcessName;
+		iProcessName = 0 ;
+	}
+	if(iBareName) {
+		delete []iBareName;
+		iBareName = 0 ;
+	}
+
+	if(iIATRefs){
+		char* tmp = reinterpret_cast<char*>(iIATRefs);
+		delete []tmp;
+		iIATRefs = 0 ;
+	}
+}
+
+TInt TRomBuilderEntry::SetCodeAlignment(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'code-align'.\n"); 
+	TInt err = Val(iCodeAlignment,aStr);	 
+	return err;
+}
+
+TInt TRomBuilderEntry::SetDataAlignment(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'data-align'.\n"); 
+	TInt align = 0;
+	Val(align,aStr);
+	if (align < 0 || (align & 0x0F) != 0) 
+		return Print(EError, "Positive multiple of 16 required for 'data-align'.\n");
+	iDataAlignment = align;
+	return KErrNone;
+}
+
+TInt TRomBuilderEntry::SetRelocationAddress(const char* aStr) {
+	if (aStr && !IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'reloc'.\n");
+	iOverrideFlags |= KOverrideAddress;
+	iRelocationAddress =  0xFFFFFFFF; 
+	if(aStr){
+		Val(iRelocationAddress,aStr);
+	}
+	return KErrNone;
+}
+
+TInt TRomBuilderEntry::SetStackReserve(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'stackreserve'.\n");	
+	TInt err = Val(iStackReserve,aStr);
+	if(err == KErrNone)
+		iOverrideFlags |= KOverrideStackReserve;
+	return err;
+}
+
+TInt TRomBuilderEntry::SetStackSize(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'stack'.\n");	
+	TInt err = Val(iStackSize,aStr);
+	if(err == KErrNone)
+		iOverrideFlags |= KOverrideStack;
+	return err;
+}
+
+TInt TRomBuilderEntry::SetHeapSizeMin(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'heapmin'.\n");	
+	TInt err = Val(iHeapSizeMin,aStr); 
+	if(err == KErrNone)
+		iOverrideFlags |= KOverrideHeapMin;
+	return KErrNone;
+}
+
+TInt TRomBuilderEntry::SetHeapSizeMax(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'heapmax'.\n");
+	TInt err = Val(iHeapSizeMax,aStr); 
+	if(err == KErrNone)
+		iOverrideFlags |= KOverrideHeapMax;
+	return err;
+}
+
+TInt TRomBuilderEntry::SetCapability(const char* aStr) {
+	iOverrideFlags |= KOverrideCapability;
+	if (IsValidNumber(aStr)) {
+		Print(EDiagnostic,"Old style numeric CAPABILTY specification ignored.\n");
+		return KErrNone;
+	}
+	return ParseCapabilitiesArg(iS.iCaps, aStr);
+}
+
+TInt TRomBuilderEntry::SetPriority(const char* aStr) {
+	if (IsValidNumber(aStr)){
+		TUint32 temp = 0 ;
+		Val(temp,aStr);
+		iPriority=(TProcessPriority)temp;
+	}
+	else {		 
+		if (stricmp(aStr, "low")==0)
+			iPriority=EPriorityLow;
+		else if (strnicmp(aStr, "background", 4)==0)
+			iPriority=EPriorityBackground;
+		else if (strnicmp(aStr, "foreground", 4)==0)
+			iPriority=EPriorityForeground;
+		else if (stricmp(aStr, "high")==0)
+			iPriority=EPriorityHigh;
+		else if (strnicmp(aStr, "windowserver",3)==0)
+			iPriority=EPriorityWindowServer;
+		else if (strnicmp(aStr, "fileserver",4)==0)
+			iPriority=EPriorityFileServer;
+		else if (strnicmp(aStr, "realtimeserver",4)==0)
+			iPriority=EPriorityRealTimeServer;
+		else if (strnicmp(aStr, "supervisor",3)==0)
+			iPriority=EPrioritySupervisor;
+		else
+			return Print(EError, "Unrecognised priority keyword.\n");
+	}
+	if (iPriority<EPriorityLow || iPriority>EPrioritySupervisor)
+		return Print(EError, "Priority out of range.\n");
+	iOverrideFlags |= KOverridePriority;
+	return KErrNone;
+}
+
+TInt TRomBuilderEntry::SetUid1(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'uid1'.\n");
+	iOverrideFlags |= KOverrideUid1;
+	Val(iUid1,aStr);
+	return KErrNone;
+}
+TInt TRomBuilderEntry::SetUid2(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'uid2'.\n");
+	iOverrideFlags |= KOverrideUid2;
+	Val(iUid2,aStr);
+	return KErrNone;
+}
+TInt TRomBuilderEntry::SetUid3(const char* aStr) {
+	if (!IsValidNumber(aStr))
+		return Print(EError, "Number required as argument for keyword 'uid3'.\n");
+	iOverrideFlags |= KOverrideUid3;
+	Val(iUid3,aStr);
+	return KErrNone;
+}
+TInt TRomBuilderEntry::SetCallEntryPoint(TBool aState) {
+	if (aState)
+		iOverrideFlags|=KOverrideCallEntryPoint;
+	else
+		iOverrideFlags|=KOverrideNoCallEntryPoint;
+	return KErrNone;
+}
+
+TInt TRomBuilderEntry::SetAttachProcess(const char* aStr) {
+
+	TInt nd=0;
+	if (*aStr==SLASH_CHAR) {
+		++aStr;
+		++nd;
+	}
+	size_t l = strlen(aStr);
+	if (l == 0)
+		return KErrGeneral;
+	const char* ss=aStr;
+	while(*ss != 0 && *ss!='.') ++ss;
+	int ext = *ss;	// 0 if no extension
+	iProcessName=new char[l+2+(ext?0:4)];
+	char* d=(char *)iProcessName;
+	strcpy(d+1, aStr);
+	if (!ext) {
+		char* t=d+1+l;
+		*t++='.';
+		*t++='e';
+		*t++='x';
+		*t++='e';
+		*t++=0;
+	}
+	char* dd=d;
+	int ind=nd;
+	while(*dd) {
+		while(*dd && *dd!=SLASH_CHAR) ++dd;
+		if (*dd==SLASH_CHAR) {
+			*dd++=0;	// change \ to NUL
+			++nd;		// count path elements
+		}
+	}
+	if (!ind && nd)
+		++nd;			// add initial \ if not present
+	*d=(char)nd;
+	return 0;
+}
+
+TInt TRomBuilderEntry::OpenImageFile()
+	{
+	TInt err = Open(iFileName);
+	return err;
+	}
+TInt TRomBuilderEntry::GetImageFileInfo(TInt aResult)
+{
+	TInt err = aResult;
+	Print(ELog,"Loading E32Image file %s \n", iFileName);
+	if (err != KErrNone) {
+		Print(EError,"File %s is not a valid E32Image file (error %d)\n", iFileName, err);
+		return err;
+	}
+	TUint hdrfmt = iHdr->HeaderFormat();
+	if (hdrfmt != KImageHdrFmt_V) {
+		Print(EError,"%s: Can't load old format binary\n", iFileName);
+		return KErrNotSupported;
+	}
+	E32ImageHeaderV* h = iHdr;
+
+	// Overide any settings in the image file with those in the obey file
+	if (iOverrideFlags & (KOverrideUid1|KOverrideUid2|KOverrideUid3)) {
+		TUint uid1 = h->iUid1;
+		TUint uid2 = h->iUid2;
+		TUint uid3 = h->iUid3;
+		if (iOverrideFlags & KOverrideUid1)
+			uid1 = iUid1;
+		if (iOverrideFlags & KOverrideUid2)
+			uid2 = iUid2;
+		if (iOverrideFlags & KOverrideUid3)
+			uid3 = iUid3;
+		SetUids(TUid::Uid(uid1), TUid::Uid(uid2), TUid::Uid(uid3));
+	}
+	if (iOverrideFlags & KOverrideStack)
+		h->iStackSize = iStackSize;
+	if (iOverrideFlags & KOverrideHeapMax)
+		h->iHeapSizeMax = iHeapSizeMax;
+	if (iOverrideFlags & KOverrideHeapMin)
+		h->iHeapSizeMin = iHeapSizeMin;
+	if (iOverrideFlags & KOverridePriority)
+		h->iProcessPriority = (TUint16)iPriority;
+	if (iOverrideFlags & KOverrideCapability)
+		h->iS.iCaps = iS.iCaps;
+	for (TInt i=0; i<SCapabilitySet::ENCapW; ++i) {
+		h->iS.iCaps[i] |= gPlatSecDisabledCaps[i];
+		h->iS.iCaps[i] &= gPlatSecAllCaps[i];
+	}
+
+	if (iOverrideFlags & KOverrideCodePaged) {
+		h->iFlags &= ~KImageCodeUnpaged;
+		h->iFlags |= KImageCodePaged;
+	}
+	if (iOverrideFlags & KOverrideCodeUnpaged) {
+		h->iFlags |= KImageCodeUnpaged;
+		h->iFlags &= ~KImageCodePaged;
+	}
+
+	if ((TInt)h->iUid1 == KExecutableImageUidValue) {
+		if (iOverrideFlags & KOverrideDataPaged) {
+			h->iFlags &= ~KImageDataUnpaged;
+			h->iFlags |= KImageDataPaged;
+		}
+		if (iOverrideFlags & KOverrideDataUnpaged) {
+			h->iFlags |= KImageDataUnpaged;
+			h->iFlags &= ~KImageDataPaged;
+		}
+	}
+
+	switch(gCodePagingOverride) {
+	case EKernelConfigPagingPolicyNoPaging:
+		h->iFlags |= KImageCodeUnpaged;
+		h->iFlags &= ~KImageCodePaged;
+		break;
+	case EKernelConfigPagingPolicyAlwaysPage:
+		h->iFlags |= KImageCodePaged;
+		h->iFlags &= ~KImageCodeUnpaged;
+		break;
+	case EKernelConfigPagingPolicyDefaultUnpaged:
+		if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
+			h->iFlags |= KImageCodeUnpaged;
+		break;
+	case EKernelConfigPagingPolicyDefaultPaged:
+		if(!(h->iFlags&(KImageCodeUnpaged|KImageCodePaged)))
+			h->iFlags |= KImageCodePaged;
+		break;
+	}
+	switch(gDataPagingOverride) {
+	case EKernelConfigPagingPolicyNoPaging:
+		h->iFlags |= KImageDataUnpaged;
+		h->iFlags &= ~KImageDataPaged;
+		break;
+	case EKernelConfigPagingPolicyAlwaysPage:
+		h->iFlags |= KImageDataPaged;
+		h->iFlags &= ~KImageDataUnpaged;
+		break;
+	case EKernelConfigPagingPolicyDefaultUnpaged:
+		if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
+			h->iFlags |= KImageDataUnpaged;
+		break;
+	case EKernelConfigPagingPolicyDefaultPaged:
+		if(!(h->iFlags&(KImageDataUnpaged|KImageDataPaged)))
+			h->iFlags |= KImageDataPaged;
+		break;
+	}
+
+	h->iCompressionType=KUidCompressionDeflate; // XIP images are always uncompressed
+
+	Print(ELog,"\t\tcompression format:0x%08x \n", h->iCompressionType);
+	if (gLogLevel & LOG_LEVEL_COMPRESSION_INFO)
+		Print(ELog,"\t\tgCompress:%d, gCompressionMethod: 0x%08x \n", gEnableCompress , gCompressionMethod);
+
+
+	// Check the uids
+
+	if ((TInt)h->iUid1 != KExecutableImageUidValue && (TInt)h->iUid1 != KDynamicLibraryUidValue) 
+		return Print(EError, "First Uid for %s is not KExecutableImageUid or KDynamicLibraryUid\n", iFileName);
+
+	// Set up the sizes and location of the distinct areas
+
+	iHeaderRange.iSize = sizeof(TRomImageHeader);
+
+	iCodeSection.iSize    = h->iTextSize;
+	iCodeSection.iFilePtr = iData + iOrigHdr->iCodeOffset;
+
+	TUint impfmt = h->ImportFormat();
+
+	if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2) {
+		TInt nimports = NumberOfImports();
+		if (nimports) {
+			iImportAddressTableSection.iSize    = (nimports+1)* sizeof(TLinAddr*);
+			iImportAddressTableSection.iFilePtr = iData + iOrigHdr->iCodeOffset + iOrigHdr->iTextSize;
+			iIATRefs = reinterpret_cast<TLinAddr **>(new char[iImportAddressTableSection.iSize ]);
+			memcpy(iIATRefs, iImportAddressTableSection.iFilePtr, iImportAddressTableSection.iSize);
+		}
+
+		if (h->iExportDirCount) {
+			iExportDirSection.iSize    = h->iExportDirCount*4;
+			iExportDirSection.iFilePtr = iData + iOrigHdr->iExportDirOffset;
+		}
+
+		// assertion - there's no rdata between IAT and Export Directory
+		TInt rdatasize = h->iCodeSize;		// overall "readonly" size
+		rdatasize -= iCodeSection.iSize;				// text
+		rdatasize -= iImportAddressTableSection.iSize;	// IAT plus trailing 0
+		rdatasize -= iExportDirSection.iSize;			// export data
+
+		if (rdatasize != 0) {
+			Print(EWarning, "Unexpected code in %s: %d bytes unexplained\n", iFileName, rdatasize);
+			// expand the code to cover text+IAT+rdata
+			iCodeSection.iSize = h->iCodeSize - iExportDirSection.iSize;
+		}
+		else {
+			if (USE_IAT_FOR_IMPORTS)
+				iCodeSection.iSize += iImportAddressTableSection.iSize;	// include IAT
+		}
+	}
+	else {
+		// ELF-derived images have no IAT and the export directory is included in the code section
+		iImportAddressTableSection.iSize    = 0;
+		iImportAddressTableSection.iFilePtr = NULL;
+		iExportDirSection.iSize    = 0;
+		iExportDirSection.iFilePtr = NULL;
+	}
+
+	if (h->iDataSize) {
+		iDataSection.iSize    = h->iDataSize;
+		iDataSection.iFilePtr = iData + iOrigHdr->iDataOffset;
+	}
+
+	iRomNode->iRomFile->iTotalDataBss = h->iDataSize + h->iBssSize;
+	iS = h->iS;
+	if (iVersionPresentInName && iVersionInName != h->ModuleVersion()) {
+		Print(EError,"%s: Version in name (%d.%d) does not match version in header (%d.%d)\n", iFileName,
+			iVersionInName>>16, iVersionInName&0x0000ffffu, h->ModuleVersion()>>16, h->ModuleVersion()&0x0000ffffu);
+		return KErrGeneral;
+	}
+	return KErrNone;
+}
+
+//
+// Approximate the required size of the file when rommed
+//
+TInt TRomBuilderEntry::SizeInRom() {
+	TInt size1, size2;
+	SizeInSections(size1,size2);
+	return size1+size2;
+}
+//
+//
+//
+void TRomBuilderEntry::LoadToRom() {
+	// Copy fixed stuff into iRomImageHeader
+	E32ImageHeaderV* h = iHdr;
+	const TUint KRomFlagMask = KImageDll | KImageNoCallEntryPoint | KImageFixedAddressExe | KImageNmdExpData | KImageDataPagingMask;
+	TUint romflags = h->iFlags & KRomFlagMask;
+	TUint abi = h->ABI();
+	TUint ept = h->EntryPointFormat();
+	TUint impfmt = h->ImportFormat();
+	romflags |= (abi | ept);
+
+	iRomImageHeader = (TRomImageHeader*)iHeaderRange.iImagePtr;
+
+	iRomImageHeader->iUid1              = h->iUid1;
+	iRomImageHeader->iUid2              = h->iUid2;
+	iRomImageHeader->iUid3              = h->iUid3;
+	iRomImageHeader->iUidChecksum       = h->iUidChecksum;
+	iRomImageHeader->iEntryPoint        = iCodeSection.iRunAddr + h->iEntryPoint;
+	iRomImageHeader->iCodeAddress       = iCodeSection.iRunAddr;
+	iRomImageHeader->iDataAddress       = iDataSection.iRunAddr;
+	iRomImageHeader->iCodeSize          = iCodeSection.iSize+iExportDirSection.iSize;
+	iRomImageHeader->iTextSize          = iCodeSection.iSize;
+	iRomImageHeader->iDataSize          = iDataSection.iSize;
+	iRomImageHeader->iBssSize           = h->iBssSize;
+	iRomImageHeader->iTotalDataSize		= iRomNode->iRomFile->iTotalDataBss;
+	iRomImageHeader->iHeapSizeMin       = h->iHeapSizeMin;
+	iRomImageHeader->iHeapSizeMax       = h->iHeapSizeMax;
+	iRomImageHeader->iStackSize         = h->iStackSize;
+	iRomImageHeader->iDllRefTable       = (TDllRefTable*)(iDllRefTableRange.iImageAddr);
+	iRomImageHeader->iExportDirCount    = h->iExportDirCount;
+	iRomImageHeader->iExportDir         = (impfmt==KImageImpFmt_ELF) ?
+		iCodeSection.iRunAddr + (h->iExportDirOffset - h->iCodeOffset)
+		: iExportDirSection.iRunAddr;
+	iRomImageHeader->iS					= h->iS;
+	iRomImageHeader->iToolsVersion		= h->iToolsVersion;
+	iRomImageHeader->iModuleVersion		= h->ModuleVersion();
+	iRomImageHeader->iFlags             = romflags | iRomImageFlags;
+	iRomImageHeader->iPriority          = h->ProcessPriority();
+	iRomImageHeader->iDataBssLinearBase = iDataBssLinearBase;
+	iRomImageHeader->iNextExtension     = 0;
+	iRomImageHeader->iHardwareVariant   = iHardwareVariant;
+	iRomImageHeader->iExceptionDescriptor = 0;
+	TUint32 xd = h->iExceptionDescriptor;
+	if ((xd & 1) && (xd != 0xffffffffu))
+		iRomImageHeader->iExceptionDescriptor = (xd & ~1) + iRomImageHeader->iCodeAddress;
+
+	if (iPreferred) {
+		iRomImageHeader->iModuleVersion	&= ~0xffffu;
+		iRomImageHeader->iModuleVersion	|= 0x8000u;
+	}
+
+	// Relocate the file to reflect the new addresses
+	Relocate();
+
+	// Copy the sections
+	iCodeSection.Load();
+	iExportDirSection.Load();
+	iDataSection.Load();
+}
+//
+// Relocates the iData to new Code and Data addresses
+//
+void TRomBuilderEntry::Relocate() {
+	TUint codeDelta=iRomImageHeader->iCodeAddress       - iHdr->iCodeBase;
+	TUint dataDelta=iRomImageHeader->iDataBssLinearBase - iHdr->iDataBase;
+
+	// code section (text, IAT, export directory)
+
+	if (iOrigHdr->iCodeRelocOffset)
+		RelocateSection(iData + iOrigHdr->iCodeOffset, iData + iOrigHdr->iCodeRelocOffset,
+		codeDelta, dataDelta, (char*)iCodeSection.iImagePtr, iIATRefs);
+
+	// data section 
+
+	if (iOrigHdr->iDataRelocOffset)
+		RelocateSection(iData + iOrigHdr->iDataOffset, iData + iOrigHdr->iDataRelocOffset, 
+		codeDelta, dataDelta, (char*)iDataSection.iImagePtr, iIATRefs);
+
+	// export directory (only for PE-derived files)
+	if (iExportDirSection.iSize) {
+		TLinAddr* ptr=(TLinAddr*)(iData + iOrigHdr->iExportDirOffset);
+
+		TLinAddr textStart = iHdr->iCodeBase;
+		TLinAddr textFinish = textStart + iHdr->iTextSize;
+		TLinAddr dataStart = textStart + iHdr->iCodeSize;
+		TLinAddr dataFinish = dataStart + iHdr->iDataSize + iHdr->iBssSize;
+
+		TInt i;
+		for (i=0; i<iHdr->iExportDirCount; i++, ptr++) {
+			TLinAddr data=*ptr+textStart;
+			if ((data>=textStart) && (data<textFinish))
+				*ptr=data+codeDelta; // export something from the text/rdata section
+			else if ((data>=dataStart) && (data<dataFinish))
+				*ptr=data+dataDelta; // export some data or bss item
+			else {
+				Print(EWarning, "Export directory in %s: item %d -> %08x, which is not text or data!\n", iFileName, i, data);
+				*ptr=0x13;	// unlucky for some
+			}
+		}
+	}
+
+	// Replace absent exports with 0
+	TLinAddr* ptr = (TLinAddr*)(iData + iOrigHdr->iExportDirOffset);
+	TInt i;
+	for (i=0; i<iHdr->iExportDirCount; i++, ptr++) {
+		if ( !( iExportBitMap[i>>3] & (1u << (i&7)) ) )
+			*ptr = 0;
+	}
+
+	// Update E32ImageHeader, in case we want to do this process again later
+
+	iHdr->iCodeBase += codeDelta;
+	iHdr->iDataBase += dataDelta;
+}
+
+
+//
+// Modify the import stubs to point directly into the export directory of the corresponding DLLs
+// using the back pointers captured by detecting relocations referring to the Import Address Table
+// The old-style Import Address Table behaviour can be retained by specifying the "keepIAT" attribute.
+//
+
+TInt TRomBuilderEntry::FixupImports(E32Rom& aRom) {
+	if (iHdr->iImportOffset == 0)
+		return KErrNone;	// nothing to do
+
+
+
+	TUint impfmt = iHdr->ImportFormat();
+	TUint my_abi = iHdr->ABI();
+	TRACE(TIMPORT,Print(ELog,"%40s[%08x] flags %08x\n",iFileName,(TUint)iHardwareVariant,iHdr->iFlags));
+	const E32ImportSection* importsection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
+	TLinAddr **iatRef=iIATRefs;
+	TAddressRange iatRange = iCodeSection;
+	iatRange.Move(iHdr->iTextSize);
+	if (USE_IAT_FOR_IMPORTS) {
+		if (impfmt == KImageImpFmt_ELF)
+			return Print(EError, "Can't retain IAT for %s since it never existed\n", iFileName);
+		if (iRomSectionNumber==0 && aRom.iObey->iSectionPosition!=-1)
+			return Print(EError, "Can't retain IAT for %s in first section - not yet implemented\n", iFileName);
+		Print(ELog, "%s has IAT at %08x\n", iFileName, iatRange.iRunAddr);
+	}
+	const E32ImportBlock* b = (const E32ImportBlock*)(importsection + 1);
+	TInt i = iHdr->iDllRefTableCount;
+	TInt numberOfImports=0;
+	TUint *impOrdinalP = (TUint*)iImportAddressTableSection.iFilePtr;	// points to original IAT in file
+	while (i-->0) {
+		char* dllname = (char*)importsection + b->iOffsetOfDllName;
+		TDllFindInfo find_info(dllname, this);
+		TBool fallback;
+		TRomNode* romnode = aRom.FindImageFileByName(find_info, EFalse, fallback);
+		if (!romnode) {
+			Print(EError, "Can't fixup imports for\n\t%s\nbecause\n\t%s\nis not in rom.\n",
+				(const char*)TModuleName(this), (const char*)TModuleName(find_info));
+			aRom.FindImageFileByName(find_info, ETrue, fallback);
+			return KErrGeneral;
+		}
+		TRomFile* dll=romnode->iRomFile;
+		TRACE(TIMPORT,Print(ELog,"%s importing from %s\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info)));
+		if (romnode->ABI() != my_abi) {
+			Print(EWarning, "File %s links to %s with different ABI\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info));
+		}
+		TInt j;
+		numberOfImports += b->iNumberOfImports;
+		if (impfmt==KImageImpFmt_ELF)
+			impOrdinalP = (TUint*)(b->Imports());	// for ELF must look in import block
+		char* codeBase = (char*)iCodeSection.iImagePtr;
+		for (j=0; j<b->iNumberOfImports; j++) {
+			TLinAddr exportAddr = 0xdeadbeef;
+			TLinAddr exporter = 0xdeadbeef;
+			TUint impOrdinal = *impOrdinalP;
+			TUint impOffset = 0;
+			if (impfmt==KImageImpFmt_ELF) {
+				TUint impd = *(TUint*)(codeBase + impOrdinal);
+				impOrdinal = impd & 0xffff;
+				impOffset = impd >> 16;
+			}
+			TRACE(TIMPORT,Print(ELog,"Ordinal %d\n", impOrdinal));
+			TInt ret=dll->AddressFromOrdinal(exporter, exportAddr, impOrdinal);
+			TRACE(TIMPORT,Print(ELog,"export %08x exporter %08x\n",exportAddr,exporter));
+			if (ret!=KErrNone) {
+				Print(EError, "%s wants ordinal %d from %s which only exports %d functions\n",
+					iFileName, impOrdinal, 	(const char*)TModuleName(find_info), dll->ExportDirCount());
+				exporter=0x13;	// unlucky for some...
+				exportAddr=0x13;
+			}
+			else if (exportAddr == 0 && impOrdinal != 0) {
+				Print(EError, "%s wants ordinal %d from %s which is absent\n",
+					iFileName, impOrdinal, 	(const char*)TModuleName(find_info));
+				exporter=0x13;	// unlucky for some...
+				exportAddr=0x13;
+			}
+			if (USE_IAT_FOR_IMPORTS) {
+				// must be PE-derived
+				*iatRef=(unsigned long*)exportAddr; //iatRange.iRunAddr;					// point into IAT ...
+				*(TLinAddr*)(iatRange.iImagePtr)=exportAddr;	// ... which has a copy of the export
+				iatRange.Move(sizeof(TLinAddr));
+				iatRef++;
+			}
+			else if (impfmt==KImageImpFmt_PE || impfmt==KImageImpFmt_PE2) {
+				**iatRef=exporter;	// point directly into export directory
+				iatRef++;
+			}
+			else {
+				// ELF-derived
+				*(TUint*)(codeBase + *impOrdinalP) = exportAddr + impOffset;
+			}
+			impOrdinalP++;
+		}
+		b = b->NextBlock(impfmt);
+	}
+	iImportCount=numberOfImports;
+	return KErrNone;
+}
+
+const char* KF32ProcessName="efile.exe";
+const char* KWservProcessName="ewsrv.exe";
+const char* KFbservProcessName="fbserv.exe";
+const char* KMdaSvrProcessName="mediaserverstub.exe";
+const char* KC32ProcessName="c32exe.exe";
+
+//
+// Work out the attach process from the file extension
+//
+// Only need to handle DLLs which run in F32, WSERV, FBSERV, MEDIASVR, C32
+// F32:		FSY FXT
+// WSERV:	ANI
+// FBSERV:
+// MDASVR:	MDA
+// C32:		CSY, PRT, TSY, AGT, AGX
+//
+const char* TRomBuilderEntry::GetDefaultAttachProcess() {
+	const char* s=(const char*)iName;
+	TInt l=strlen(s);
+	if (l<4 || s[l-4]!='.')
+		return NULL;
+	s+=(l-3);
+	if (stricmp(s,"fsy")==0)
+		return KF32ProcessName;
+	if (stricmp(s,"fxt")==0)
+		return KF32ProcessName;
+	if (stricmp(s,"ani")==0)
+		return KWservProcessName;
+	if (stricmp(s,"mda")==0)
+		return KMdaSvrProcessName;
+	if (stricmp(s,"csy")==0)
+		return KC32ProcessName;
+	if (stricmp(s,"prt")==0)
+		return KC32ProcessName;
+	if (stricmp(s,"tsy")==0)
+		return KC32ProcessName;
+	if (stricmp(s,"agt")==0)
+		return KC32ProcessName;
+	if (stricmp(s,"agx")==0)
+		return KC32ProcessName;
+	return NULL;
+}
+
+TInt TRomBuilderEntry::FindAttachProcess(E32Rom& aRom) {
+	if (iRomImageFlags & (KRomImageFlagVariant|KRomImageFlagExtension|KRomImageFlagDevice))
+		return KErrNone;
+	const char* attp_name=(const char*)iProcessName;
+	int nd=0;
+	if (attp_name)
+		nd=*attp_name++;
+	else
+		attp_name=GetDefaultAttachProcess();
+	if (!attp_name)
+		return KErrNone;
+	TInt i;
+	TUint my_abi = iHdr->ABI();
+	TUint abi = 0;
+	if (nd) {
+		// path search
+		TRomNode* rn=aRom.iObey->iRootDirectory;
+		for (; nd; --nd) {
+			rn=rn->FindInDirectory(attp_name);
+			if (!rn) {
+				Print(EError, "Invalid attach process name element %s\n", attp_name);
+				return KErrGeneral;
+			}
+			attp_name+=(strlen(attp_name)+1);
+		}
+		iRomNode->iRomFile->iAttachProcess=rn->iRomFile;
+		abi = iRomNode->iRomFile->iAttachProcess->ABI();
+	}
+	else {
+		// filename only search
+		for (i=0; i<aRom.iObey->iNumberOfPeFiles; i++) {
+			TRomBuilderEntry* e=aRom.iPeFiles[i];
+			abi = e->iHdr->ABI();
+			if (stricmp((const char*)e->iName, attp_name)==0) {
+				if (iRomNode->iRomFile->iAttachProcess) {
+					Print(EError, "Ambiguous attach process name %s\n", attp_name);
+					return KErrGeneral;
+				}
+				iRomNode->iRomFile->iAttachProcess=e->iRomNode->iRomFile;
+			}
+		}
+	}
+	if (abi != my_abi) {
+		Print(EWarning, "File %s: Attach process has different ABI\n", (const char*)TModuleName(this));
+	}
+	return KErrNone;
+}
+//
+// Fill in the iDeps
+//
+TInt TRomBuilderEntry::BuildDependenceGraph(E32Rom& aRom) {
+	TBool is_kernel = ((iRomImageFlags & KRomImageFlagsKernelMask) != 0);
+	TRomNode* rn = iRomNode;
+	TRomFile* rf = rn->iRomFile;
+	TUint my_abi = iHdr->ABI();
+	TUint impfmt = iHdr->ImportFormat();
+	rf->iNumDeps = iHdr->iDllRefTableCount;
+	if (IsDll() && aRom.iObey->iMemModel!=E_MM_Flexible && aRom.iObey->iMemModel!=E_MM_Multiple && (iHdr->iDataSize!=0 || iHdr->iBssSize!=0)) {
+		TInt r=FindAttachProcess(aRom);
+		if (r!=KErrNone)
+			return r;
+		if (aRom.iObey->iMemModel==E_MM_Moving) {
+			if (rf->iAttachProcess && !(rf->iAttachProcess->RomImageFlags() & KRomImageFlagFixedAddressExe))
+				rf->iAttachProcess=NULL;	// ignore attach process if not fixed
+		}
+	}
+	TRomFile* attp=rf->iAttachProcess;
+	if (attp)
+		++rf->iNumDeps;		// extra implicit dependence on process
+	if (rf->iNumDeps) {
+		rf->iDeps=new TRomFile* [rf->iNumDeps];
+		memset(rf->iDeps, 0, rf->iNumDeps*sizeof(TRomFile*));
+	}
+
+	TInt err = KErrNone;
+	const E32ImportSection* importSection = (const E32ImportSection*)(iData + iOrigHdr->iImportOffset);
+	const E32ImportBlock* block = (const E32ImportBlock*)(importSection + 1);
+	TInt i;
+	for (i=0; i<iHdr->iDllRefTableCount; i++, block = block->NextBlock(impfmt), TRACE(TIMPORT,Print(ELog,"DllRef/dll done\n")) ) {
+		char* dllname = (char*)importSection + block->iOffsetOfDllName;
+		TDllFindInfo find_info(dllname, this);
+		TBool fallback;
+		TRomNode* romnode = aRom.FindImageFileByName(find_info, EFalse, fallback);
+		if (!romnode) {
+			Print(EError, "Can't build dependence graph for\n\t%s\nbecause\n\t%s\nis not in rom.\n",
+				(const char*)TModuleName(this), (const char*)TModuleName(find_info));
+			aRom.FindImageFileByName(find_info, ETrue, fallback);
+			err = KErrNotFound;
+			continue;
+		}
+		if (fallback) {
+			Print(EWarning, "File %s links to %s\n\twhich is not in ROM. Version 1.0 of latter used instead.\n",
+				(const char*)TModuleName(this), (const char*)TModuleName(find_info));
+		}
+		TRACE(TIMPORT,Print(ELog,"%s links to %s\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info)));
+		TRACE(TIMPORT,Print(ELog,"Resolves to %s\n", (const char*)TModuleName(*romnode)));
+		TBool dep_is_kernel = ((romnode->iRomFile->RomImageFlags() & KRomImageFlagsKernelMask) != 0);
+		if (dep_is_kernel != is_kernel) {
+			if (is_kernel) {
+				Print(EError, "Kernel side executable\n\t%s\nlinks to user side executable\n\t%s\n",
+					(const char*)TModuleName(this), (const char*)TModuleName(find_info));
+			}
+			else {
+				Print(EError, "User side executable\n\t%s\nlinks to kernel side executable\n\t%s\n",
+					(const char*)TModuleName(this), (const char*)TModuleName(find_info));
+			}
+			err = KErrGeneral;
+			continue;
+		}
+		// prevent the situiation which importer is primary, variant or extension, exporter is device
+		if (is_kernel && !Device() && romnode->iRomFile->iRbEntry->Device())	 {
+			Print(EWarning, "Kernel/variant/extension\n\t%s\nlinks to non-extension LDD/PDD\n\t%s\n",
+				(const char*)TModuleName(this), (const char*)TModuleName(find_info));
+		}
+		if (romnode->ABI() != my_abi) {
+			Print(EWarning, "File %s links to %s with different ABI\n", (const char*)TModuleName(this), (const char*)TModuleName(find_info));
+		}
+
+		rf->iDeps[i]=romnode->iRomFile;
+		const SSecurityInfo& s1 = iHdr->iS;
+		const SSecurityInfo& s2 = romnode->iRomFile->SecurityInfo();
+		TInt r = CompareCapabilities(s1.iCaps, s2.iCaps, iFileName, dllname);
+		if (r != KErrNone)
+			err = r;
+		if (romnode->iRomFile==attp)
+			attp=NULL;
+	}
+
+	if (attp)
+		rf->iDeps[rf->iNumDeps-1]=attp;
+	TRACE(TIMPORT,Print(ELog,"BuildDep done all\n"));
+	return err;
+}
+//
+// Fill in the DLLRefTable
+//
+TInt TRomBuilderEntry::ResolveDllRefTable(E32Rom& aRom) {
+	TRomNode* rn = iRomNode;
+	TRomFile* rf = rn->iRomFile;
+	(void)aRom;
+	if (rf->iNumPDeps==0)
+		return KErrNone;	// nothing to do
+
+	TDllRefTable* dllRefTable=(TDllRefTable*)(iDllRefTableRange.iImagePtr);
+
+	TUint16 flags=0;
+
+	dllRefTable->iFlags=flags;
+	dllRefTable->iNumberOfEntries=(TUint16)rf->iNumPDeps;
+
+	TInt err = KErrNone;
+	TInt i;
+	for (i=0; i<rf->iNumPDeps; i++) {
+		dllRefTable->iEntry[i]=(TRomImageHeader*)rf->iPDeps[i]->iAddresses.iRunAddr;
+	}
+	TRACE(TIMPORT,Print(ELog,"DllRef done all\n"));
+	return err;
+}
+
+void TRomBuilderEntry::DisplaySize(TPrintType aWhere) {
+	if(gLogLevel > DEFAULT_LOG_LEVEL){
+
+		if(gLogLevel & LOG_LEVEL_FILE_DETAILS) {
+			// More detailed information about file name in .
+			TBool aIgnoreHiddenAttrib = ETrue;
+			TInt aLen = iRomNode->FullNameLength(aIgnoreHiddenAttrib);
+			char * aBuf = new char[aLen+1];
+			iRomNode->GetFullName(aBuf, aIgnoreHiddenAttrib);
+			if (iPatched|iRomNode->iHidden)
+				Print(aWhere, "%s\t%d\t%s\t%s\n", iFileName, SizeInRom(), iPatched?"patched":"hidden", aBuf);
+			else
+				Print(aWhere, "%s\t%d\t%s\n", iFileName, SizeInRom(), aBuf);
+			delete[] aBuf;
+		}
+	}
+	else{
+		if (iPatched|iRomNode->iHidden)
+			Print(aWhere, "%s\t%d\t%s\n", iFileName, SizeInRom(), iPatched?"patched":"hidden");
+		else
+			Print(aWhere, "%s\t%d\n", iFileName, SizeInRom());
+	}
+}
+
+/**
+* TRomFile iRomEntry is a linked list through the various
+* distinct TRomEntry objects which may exist for the associated file
+* due to variant processing / aliasing
+*/
+
+void TRomFile::SetRomEntry(TRomEntry* aEntry) {
+	// Need to add to the tail of the list, for backwards compatibility
+	// Adding to the front of the list changes the iPrimary and iSecondary
+	// values in the TRomHeader when multiple variants are present
+
+	if (iFinal)
+		return;			// address already established so no fixup required
+	if (iRomEntry==0) {
+		iRomEntry = aEntry;
+		return;
+	}
+	TRomEntry* entry = iRomEntry;
+	while (entry->iAddressLin != 0)
+		entry = (TRomEntry*)entry->iAddressLin;
+	entry->iAddressLin = (TLinAddr)aEntry;
+}
+
+void TRomBuilderEntry::FixupRomEntries(TInt aSize) {
+	if (iPatched)
+		return;		// patched files don't appear in the ROM file system
+
+	iRomNode->Finalise(aSize);
+}
+
+/**
+* TRomNode::Finalise updates the associated TRomEntry objects with the final size and
+* linear address information supplied by the TRomBuilderEntry. It also stores the
+* summary information for resolving static linkages to this executable (if appropriate)
+* and adjusts the TRomNodes so that they are identical to the ones which would be 
+* obtained by walking the directory structure in an existing ROM.
+*/
+void TRomNode::Finalise(TInt aSize) {
+	TRACE(TIMPORT,Print(ELog,"TRomNode %s Finalise %08x %d\n", (const char*)TModuleName(*this), iRomFile->iFinal));
+	iRomFile->Finalise(aSize);
+}
+
+/**
+* TRomFile::Finalise updates the associated TRomEntry objects with the final size and
+* linear address information supplied by the TRomBuilderEntry. It also stores the
+* summary information for resolving static linkages to this executable (if appropriate)
+* and adjusts the TRomFiles so that they are identical to the ones which would be 
+* obtained by walking the directory structure in an existing ROM.
+*/
+void TRomFile::Finalise(TInt aSize) {
+	if (iFinal)
+		return;
+	TLinAddr ra = iRbEntry->iHeaderRange.iImageAddr;
+	TRomEntry* entry = iRomEntry;
+	while (entry) {
+		TRomEntry* next = (TRomEntry*)entry->iAddressLin;
+		entry->iSize = aSize;
+		entry->iAddressLin = ra;
+		entry = next;
+	}
+	iAddresses = iRbEntry->iHeaderRange;
+	iAddresses.iSize = aSize;
+	if ((!iRbEntry->iResource) && (!iRbEntry->HCRDataFile())) {
+		iExportDir = iAddresses;
+		iExportDir.iSize = iRbEntry->iHdr->iExportDirCount * sizeof(TLinAddr);
+		iExportDir.Move(RomImgHdr()->iExportDir - iAddresses.iRunAddr);
+	}
+	iRbEntry = 0;
+	iFinal = ETrue;
+}
+
+void TRomBuilderEntry::SetRomNode(TRomNode* aNode) {
+	iRomNode = aNode;
+}
+
+
+void TImageSection::Load() const
+{ 
+	if (iSize && iImagePtr && iFilePtr) 
+		memcpy(iImagePtr,iFilePtr,iSize); 
+}
+
+/**
+* TDllExportInfo is the information about a DLL which is necessary to
+* resolve a static link to that DLL. It all comes from the TRomImageHeader,
+* as it would with a static linkage resolved at runtime.
+*/
+TRomFile::TRomFile() {
+	memset(this, 0, sizeof(TRomFile));
+	iRefCount = 1;
+	iHwvd = KVariantIndependent;
+	iDataBssOffsetInExe = -1;
+}
+
+TRomFile::~TRomFile() {
+	if(iDeps) delete[] iDeps;
+	if(iPDeps) delete[] iPDeps;
+}
+//
+// Get the export address of symbol aOrdinal
+//
+
+TInt TRomFile::AddressFromOrdinal(TLinAddr& aEDataAddr, TLinAddr& aExport, TUint aOrdinal) {
+	if(aOrdinal == 0) {
+		aEDataAddr = iExportDir.iRunAddr -1 ;
+		aExport = *(TLinAddr*)((TLinAddr*)iExportDir.iImagePtr - 1);
+		if((TInt)aExport == ExportDirCount()) {
+			aEDataAddr = 0;
+			aExport = 0;
+		}
+		return KErrNone;
+	}
+
+	TUint index = aOrdinal - KOrdinalBase;
+	if (index >= (TUint)ExportDirCount())
+		return KErrNotFound;
+	aEDataAddr = iExportDir.iRunAddr + index * sizeof(TLinAddr);
+	aExport = ((TLinAddr*)iExportDir.iImagePtr)[index];
+	return KErrNone;
+}
+
+
+bool TRomFile::ComputeSmpSafe(const TRomBuilderEntry* aRbEntry) {
+	// A component is SMP safe if:
+	//
+	// 1. It's E32 image file is marked as SMP safe (MMP keyword SMPSAFE).
+	// 2. All components it links to are SMP safe.
+	//
+	// This implies a recursive dependency structure.
+
+	if (iSmpInfo.isInit) {
+		// We have already visited this node.
+		return iSmpInfo.isSafe;
+	}
+
+	// Mark this node as "active," meaning that we are currently evaluating it. We
+	// use this to detect cycles in the dependency graph.
+	iSmpInfo.isActive = 1;
+
+	iSmpInfo.isSafe = 1;
+
+	// Have we found any cycle in the graph?
+	bool is_cycle = 0;
+
+	if ( aRbEntry->iOrigHdr->iFlags & KImageSMPSafe ) {
+		// OK, the E32 file for this node is marked as SMPSAFE. Now we need to check
+		// that all nodes we depend on are SMP safe.
+
+		for (int i = 0; i < iNumDeps; i++) {
+			TRomFile* e = iDeps[i];
+
+			assert(this != e);
+
+			if (e->iSmpInfo.isActive) {
+				is_cycle = 1;
+			}
+			else if ( ! e->ComputeSmpSafe(e->iRbEntry) ) {
+				if (gLogLevel & LOG_LEVEL_SMP_INFO) {
+					Print(ELog,"SMP-unsafe: %s: links to unsafe component %s.\n",
+						aRbEntry->iBareName , e->iRbEntry->iBareName);
+				}
+
+				iSmpInfo.isSafe = 0;
+				break;
+			}
+		}
+	}
+	else {
+		if (gLogLevel & LOG_LEVEL_SMP_INFO) {
+			Print(ELog,"SMP-unsafe: %s: MMP keyword SMPSAFE not used.\n", aRbEntry->iBareName);
+		}
+
+		iSmpInfo.isSafe = 0;
+	}
+
+	iSmpInfo.isActive = 0;
+
+	if (!iSmpInfo.isSafe || !is_cycle) {
+		iSmpInfo.isInit = 1;
+	}
+
+	return iSmpInfo.isSafe;
+}
+
+/**
+* TRomNode::CopyDirectory performs a deep copy of the TRomNode structure
+*/
+TRomNode* TRomNode::CopyDirectory(TRomNode*& aLastExecutable, TRomNode* aParent) {
+	if (iHidden && iChild==0) {
+		// Hidden file - do not copy (as it wouldn't be visible in the ROM filestructure)
+		if (iSibling)
+			return iSibling->CopyDirectory(aLastExecutable, aParent);
+		else
+			return 0;
+	}
+
+	TRomNode* copy = new TRomNode(*this);
+	copy->iParent = aParent;
+	if(aLastExecutable==0)
+		aLastExecutable = copy;		// this must be the root of the structure
+
+	// recursively copy the sub-structures
+	if (iChild)
+		copy->iChild = iChild->CopyDirectory(aLastExecutable, copy);
+	if (iSibling)
+		copy->iSibling = iSibling->CopyDirectory(aLastExecutable, aParent);
+
+	if (copy->iAtt & KEntryAttXIP)
+		AddExecutableFile(aLastExecutable,copy);
+	return copy;
+}
+
+TInt TRomNode::Alias(TRomNode* aNode, TRomNode*& aLastExecutable) {
+	if (aNode->iAtt & KEntryAttXIP)
+		AddExecutableFile(aLastExecutable,this);
+	return SetBareName();
+}
+
+TInt TRomNode::Rename(TRomNode *aOldParent, TRomNode* aNewParent, const char* aNewName) {
+	aOldParent->Remove(this);
+	aNewParent->Add(this);
+	if(iName)
+		delete []iName;
+	iName = NormaliseFileName(aNewName);
+	return SetBareName();
+}
+
+TInt TRomNode::SetBareName() {
+	if(iBareName) {
+		delete []iBareName;
+		iBareName = 0 ;
+	}
+	TUint32 uid;
+	TUint32 vin;
+	TUint32 flg;
+	iBareName = SplitFileName(iName, uid, vin, flg);
+	if (uid || (flg & EUidPresent))
+		return KErrBadName;
+	if (strchr(iBareName, '{') || strchr(iBareName, '}'))
+		return KErrBadName;
+	if ((iAtt & KEntryAttXIP) && (flg & EVerPresent)) {
+		TUint32 ver = iRomFile->ModuleVersion();
+		if (ver != vin)
+			return KErrArgument;
+	}
+	return KErrNone;
+}