diff -r 238f4cb8391f -r ad8ffc8e1982 imgtools/romtools/rombuild/r_build.cpp --- a/imgtools/romtools/rombuild/r_build.cpp Thu Jun 10 13:50:24 2010 +0800 +++ b/imgtools/romtools/rombuild/r_build.cpp Mon Jul 26 11:04:29 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 -#include -#include -#include -#include -#include -#include "u32std.h" -#include -#include -#include "h_utl.h" - -#define USE_IAT_FOR_IMPORTS (iOverrideFlags&KOverrideKeepIAT || (iHdr->iCpuIdentifier & 0x1000)) - -#if defined(__MSVCDOTNET__) || defined(__TOOLS2__) -#include -#else //!__MSVCDOTNET__ -#include -#endif - -#if defined(__MSVCDOTNET__) || defined(__TOOLS2__) -#include -#else //!__MSVCDOTNET__ -#include -#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<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>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; iCreateRomEntries(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 (iPriorityEPrioritySupervisor) - 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; iiS.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; iiExportDirCount; i++, ptr++) - { - TLinAddr data=*ptr+textStart; - if ((data>=textStart) && (data=dataStart) && (data %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; iiExportDirCount; 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; jiNumberOfImports; 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; iiNumberOfPeFiles; 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; iiDllRefTableCount; 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; iiNumPDeps; 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 +#include +#include +#include +#include +#include +#include "u32std.h" +#include +#include +#include "h_utl.h" + +#define USE_IAT_FOR_IMPORTS (iOverrideFlags&KOverrideKeepIAT || (iHdr->iCpuIdentifier & 0x1000)) + +#include +#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<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>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; iCreateRomEntries(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(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 (iPriorityEPrioritySupervisor) + 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; iiS.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(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; iiExportDirCount; i++, ptr++) { + TLinAddr data=*ptr+textStart; + if ((data>=textStart) && (data=dataStart) && (data %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; iiExportDirCount; 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; jiNumberOfImports; 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; iiNumberOfPeFiles; 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; iiDllRefTableCount; 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; iiNumPDeps; 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; +}