1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kernel/eka/memmodel/emul/win32/mcodeseg.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1155 @@
1.4 +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32\memmodel\emul\win32\mcodeseg.cpp
1.18 +//
1.19 +//
1.20 +
1.21 +#define __INCLUDE_ALL_SUPPORTED_CAPABILITIES__
1.22 +#include "memmodel.h"
1.23 +#include <property.h>
1.24 +#include <emulator.h>
1.25 +#include <wchar.h>
1.26 +
1.27 +#define __CHECKHEAP() ((RHeapK*)K::Allocator)->Check()
1.28 +
1.29 +static TBool BootComplete; // flag set when boot EXE is loaded as an EPOC process
1.30 +static DWin32CodeSeg* KernelCodeSeg;
1.31 +static HMODULE KernelModuleHandle;
1.32 +
1.33 +GLREF_C TInt CompareCodeSegsByName(const DCodeSeg& aA, const DCodeSeg& aB);
1.34 +
1.35 +void TruncToNarrow(TUint8* aDes, const TUint16* aSrc, int aLen)
1.36 + {
1.37 + //converts to narrow by dumping the high order byte
1.38 + if(aDes && aSrc)
1.39 + {
1.40 + if(aLen==-1)
1.41 + {
1.42 + for(int index=0;*aSrc;index++)
1.43 + *aDes++ = (TUint8)*aSrc++;
1.44 + *aDes = '\0';
1.45 + }
1.46 + else
1.47 + for(int index=0;index<aLen;index++)
1.48 + *aDes++ = (TUint8)*aSrc++;
1.49 + }
1.50 + }
1.51 +
1.52 +void ExpandToWide(TUint16* aDes, const TUint8* aSrc, int aLen)
1.53 + {
1.54 + if(aDes && aSrc)
1.55 + {
1.56 + for(int index=0;index<aLen;index++)
1.57 + *aDes++ = (TUint16)*aSrc++;
1.58 + }
1.59 + }
1.60 +
1.61 +#ifdef KDLL
1.62 +void DumpWin32CodeSeg(DWin32CodeSeg& a)
1.63 + {
1.64 + const TUint32* uid=(const TUint32*)&a.iUids;
1.65 + Kern::Printf("DWin32CodeSeg@%08x:",&a);
1.66 + Kern::Printf("iLink = %08x %08x", a.iLink.iNext, a.iLink.iPrev);
1.67 + Kern::Printf("iTempLink = %08x %08x", a.iTempLink.iNext, a.iTempLink.iPrev);
1.68 + Kern::Printf("iGbgLink = %08x %08x", a.iGbgLink.iNext, a.iGbgLink.iPrev);
1.69 + Kern::Printf("iAccessCount = %d", a.iAccessCount);
1.70 + Kern::Printf("iEntryPtVeneer = %08x", a.iEntryPtVeneer);
1.71 + Kern::Printf("iFileEntryPoint = %08x", a.iFileEntryPoint);
1.72 + Kern::Printf("iFileName = %lS", a.iFileName);
1.73 + Kern::Printf("iRootName = %lS", &a.iRootName);
1.74 + Kern::Printf("iExtOffset = %d", a.iExtOffset);
1.75 + Kern::Printf("iModuleVersion = %08x", a.iModuleVersion);
1.76 + Kern::Printf("iUids = %08x %08x %08x", uid[0], uid[1], uid[2]);
1.77 + Kern::Printf("iDepCount=%d iDeps=%08x", a.iDepCount, a.iDeps);
1.78 + Kern::Printf("iNextDep=%d, iMark=%08x, iAttr=%08x", a.iNextDep, a.iMark, a.iAttr);
1.79 + Kern::Printf("iExeCodeSeg=%08x, iAttachProcess=%O", a.iExeCodeSeg, a.iAttachProcess);
1.80 + Kern::Printf("iWinInstance = %08x", a.iWinInstance);
1.81 + Kern::Printf("iModuleHandle = %08x", a.iModuleHandle);
1.82 + Kern::Printf("iModuleFile = %08x", a.iModuleFile);
1.83 + Kern::Printf("iAlwaysLoaded = %08x", a.iAlwaysLoaded);
1.84 + Kern::Printf("iModuleList = %08x", a.iModuleList);
1.85 + }
1.86 +#endif
1.87 +
1.88 +void ExecInEntryPoint()
1.89 + {
1.90 + // This function will be called if an Exec:: call is attempted in the entry
1.91 + // point of a DLL which didn't specify 'epocallowdlldata'
1.92 + Kern::Fault("BAD DLL STATIC",0);
1.93 + }
1.94 +
1.95 +static const SFastExecTable DummyFastExecTable={0,{0}};
1.96 +static const SSlowExecTable DummySlowExecTable={0,(TLinAddr)ExecInEntryPoint,0,{{0,0}}};
1.97 +
1.98 +// Force a call to a DLL entry point to initialise any gratuitous writeable data
1.99 +// generated by the compiler.
1.100 +// Change exec table to prevent any executive calls in case someone forgot to
1.101 +// use the 'epocallowdlldata' option.
1.102 +void ForceEntryPointCall(TLinAddr aEntryPoint)
1.103 + {
1.104 + __KTRACE_OPT(KDLL,Kern::Printf("ForceEntryPoint %08x", aEntryPoint));
1.105 + NKern::Lock();
1.106 + NThread* nthrd = NKern::CurrentThread();
1.107 + const SFastExecTable* fast = nthrd->iFastExecTable;
1.108 + const SSlowExecEntry* slow = nthrd->iSlowExecTable;
1.109 + nthrd->iFastExecTable = (SFastExecTable*)&DummyFastExecTable;
1.110 + nthrd->iSlowExecTable = DummySlowExecTable.iEntries;
1.111 + TLibraryEntry ep = (TLibraryEntry)aEntryPoint;
1.112 + (*ep)(KModuleEntryReasonProcessAttach);
1.113 + nthrd->iFastExecTable = fast;
1.114 + nthrd->iSlowExecTable = slow;
1.115 + NKern::Unlock();
1.116 + }
1.117 +
1.118 +class TWin32Filename
1.119 + {
1.120 +public:
1.121 + inline TWin32Filename()
1.122 + {iBuf[0] = '\0';}
1.123 + inline TWin32Filename(const TDesC& aFilename)
1.124 + {Set(aFilename);}
1.125 + inline TWin32Filename& operator=(const TDesC& aFilename)
1.126 + {Set(aFilename);return *this;}
1.127 + inline operator LPCWSTR() const
1.128 + {return iBuf;}
1.129 +private:
1.130 + void Set(const TDesC& aFilename);
1.131 +private:
1.132 + WCHAR iBuf[KMaxFileName + 1];
1.133 + };
1.134 +
1.135 +void TWin32Filename::Set(const TDesC& aFilename)
1.136 + {
1.137 + TUint16 fileName[KMaxFileName];
1.138 + ExpandToWide(fileName, aFilename.Ptr(), aFilename.Length());
1.139 + TPtr p((TUint8*)iBuf,KMaxFileName<<1);
1.140 + Property::MapFilename(p, TPtrC((TUint8*)fileName,aFilename.Length()<<1));
1.141 + iBuf[p.Length()>>1] = '\0';
1.142 + }
1.143 +
1.144 +class DModuleList : public DBase
1.145 + {
1.146 +public:
1.147 + enum TFlags
1.148 + {
1.149 + EFlagData=0x01,
1.150 + EFlagDataPresent=0x02,
1.151 + EFlagAlreadyLoaded=0x04,
1.152 + EFlagMark=0x08,
1.153 + EFlagExe=0x10,
1.154 + EFlagAlwaysLoaded=0x20,
1.155 + EFlagExeInTree=0x40,
1.156 + };
1.157 +
1.158 + struct SModule
1.159 + {
1.160 + TLinAddr iModuleHandle;
1.161 + DWin32CodeSeg* iCodeSeg;
1.162 + TUint32 iFlags;
1.163 + SSecurityInfo iS;
1.164 + TUint32 iModuleVersion;
1.165 + TInt iDepCount;
1.166 + TInt* iDepList;
1.167 + };
1.168 +public:
1.169 + DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess);
1.170 + virtual ~DModuleList();
1.171 + TInt Find(TInt aModule);
1.172 + TInt GatherDependencies(HMODULE aModule);
1.173 + TInt CompileDepLists();
1.174 + void SetFlags();
1.175 + TUint32 Flags(SModule* aM);
1.176 + TInt LoadDependencies();
1.177 + void LinkDependencies();
1.178 + TInt Loaded();
1.179 +public:
1.180 + DWin32CodeSeg* iMain;
1.181 + DProcess* iAttachProcess;
1.182 + RArray<SModule> iModules;
1.183 + };
1.184 +
1.185 +DModuleList::DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess)
1.186 + : iMain(aMainSeg), iAttachProcess(aProcess),
1.187 + iModules(8, _FOFF(SModule,iModuleHandle), 2*256)
1.188 + {
1.189 + }
1.190 +
1.191 +DModuleList::~DModuleList()
1.192 + {
1.193 + TInt c = iModules.Count();
1.194 + if (c)
1.195 + {
1.196 + SModule* pM = (SModule*)&iModules[0];
1.197 + SModule* pE = pM + c;
1.198 + for (; pM<pE; ++pM)
1.199 + {
1.200 + Kern::Free(pM->iDepList);
1.201 + }
1.202 + }
1.203 + iModules.Close();
1.204 + }
1.205 +
1.206 +TInt DModuleList::Find(TInt aModule)
1.207 + {
1.208 + SModule mod;
1.209 + mod.iModuleHandle=(TLinAddr)aModule;
1.210 + return iModules.FindInUnsignedKeyOrder(mod);
1.211 + }
1.212 +/**
1.213 +Populate iModules with SModule entries corresponding to supplied HModule and all of its dependencies,
1.214 +direct and indirect.
1.215 +
1.216 +@param aModule A Windows module handle
1.217 +@return KErrNone if successful
1.218 +*/
1.219 +TInt DModuleList::GatherDependencies(HMODULE aModule)
1.220 + {
1.221 + __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
1.222 + Emulator::TModule etm(aModule);
1.223 + SModule mod;
1.224 + mod.iModuleHandle=(TLinAddr)aModule;
1.225 + mod.iCodeSeg=NULL;
1.226 + mod.iDepList=NULL;
1.227 +
1.228 + TUint32 uid[3];
1.229 + TUidType& uidref=*(TUidType*)uid;
1.230 + const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
1.231 + if (!hdr)
1.232 + return KErrNotSupported;
1.233 + __KTRACE_OPT(KDLL,Kern::Printf("Module flags %08x, cap %08x %08x, sid %08x", hdr->iFlags, hdr->iS.iCaps[1], hdr->iS.iCaps[0], hdr->iS.iSecureId));
1.234 + mod.iS = hdr->iS;
1.235 + // Overide capabilities in image
1.236 + const SCapabilitySet& disabledCaps = *(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
1.237 + for(TInt i=0; i<SCapabilitySet::ENCapW; i++)
1.238 + {
1.239 + mod.iS.iCaps[i] |= disabledCaps[i];
1.240 + mod.iS.iCaps[i] &= AllSupportedCapabilities[i];
1.241 + }
1.242 + mod.iModuleVersion = hdr->iModuleVersion;
1.243 + mod.iFlags = (hdr->iFlags & KEmulatorImageFlagAllowDllData) ? EFlagData|EFlagDataPresent : 0;
1.244 + uidref = *(const TUidType*)&hdr->iUids[0];
1.245 + TBool isExe = (uid[0]==KExecutableImageUidValue);
1.246 + TBool data_section_present = (etm.Section(KWin32SectionName_EpocData) != NULL);
1.247 + if (data_section_present && isExe)
1.248 + mod.iFlags = EFlagData|EFlagDataPresent;
1.249 + __KTRACE_OPT(KDLL,Kern::Printf("DataSectionPresent = %x", data_section_present));
1.250 +
1.251 + // Can't do this for CodeWarrior since it sticks everything in .data, even constants
1.252 + // On VC6 this check works for Base code, but not for some other code.
1.253 +// if (data_section_present && !isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
1.254 +// return KErrNotSupported;
1.255 +
1.256 + if (!data_section_present)
1.257 + mod.iFlags = 0;
1.258 + if (isExe)
1.259 + mod.iFlags |= EFlagExe|EFlagExeInTree;
1.260 +
1.261 + SWin32Module w32m;
1.262 + w32m.iWin32ModuleHandle=(TLinAddr)aModule;
1.263 + w32m.iCodeSeg=NULL;
1.264 + TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
1.265 + __KTRACE_OPT(KDLL, Kern::Printf("GlobalIx=%d", ix));
1.266 + if ((ix>=0 && !MM::Win32Modules[ix].iCodeSeg) || aModule==KernelModuleHandle)
1.267 + mod.iFlags|=EFlagAlwaysLoaded;
1.268 + TInt r=iModules.InsertInUnsignedKeyOrder(mod);
1.269 + __KTRACE_OPT(KDLL, Kern::Printf("Flags=%08x, InsertRes=%d", mod.iFlags, r));
1.270 + if (r==KErrAlreadyExists)
1.271 + return KErrNone;
1.272 + if (r!=KErrNone)
1.273 + return r;
1.274 + if (mod.iFlags & EFlagAlwaysLoaded)
1.275 + return KErrNone; // stop if we reach an extension or variant
1.276 + if (data_section_present && (mod.iFlags & EFlagData)==0)
1.277 + {
1.278 + // DLL, .data present but 'epocallowdlldata' not specified
1.279 + // - either the compiler forgetting that something's constant or
1.280 + // developer forgetting to specify 'epocallowdlldata'.
1.281 + // call entry point from here to keep the compiler happy
1.282 + const char* entry_name = "_E32Dll" ;
1.283 + TLinAddr ep = (TLinAddr)Emulator::GetProcAddress(aModule, entry_name);
1.284 + __NK_ASSERT_ALWAYS(ep!=0);
1.285 + ForceEntryPointCall(ep);
1.286 + }
1.287 +
1.288 + const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
1.289 + if (imports)
1.290 + {
1.291 + for (; imports->Characteristics; ++imports )
1.292 + {
1.293 + __KTRACE_OPT(KDLL, { TPtrC8 n((const TText8*)etm.Translate(imports->Name)); Kern::Printf("Importing from %S", &n);} );
1.294 + Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
1.295 +
1.296 + if (!imp_etm.IsValid())
1.297 + {
1.298 + __KTRACE_OPT(KDLL, Kern::Printf("Spurious import"));
1.299 + continue;
1.300 + }
1.301 +
1.302 + if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
1.303 + {
1.304 + __KTRACE_OPT(KDLL, Kern::Printf("Not EPOC Module"));
1.305 + continue; // not an epoc DLL
1.306 + }
1.307 +
1.308 + r=GatherDependencies(imp_etm.iModule);
1.309 + if (r!=KErrNone)
1.310 + return r;
1.311 + }
1.312 + }
1.313 + __KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
1.314 + return KErrNone;
1.315 + }
1.316 +
1.317 +#ifdef __VC32__
1.318 +#pragma warning( disable : 4701 ) // disable warning C4701: local variable 'missingCaps' may be used without having been initialized
1.319 +#endif
1.320 +
1.321 +/**
1.322 +Iterate through imports (if any) of each SModule in list. Populate iDepList with the indicies (in iModules)
1.323 +of directly required modules. Checks that dependencies are legal under platsec.
1.324 +@return KErrNone on success.
1.325 +*/
1.326 +TInt DModuleList::CompileDepLists()
1.327 + {
1.328 + __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::CompileDepLists"));
1.329 + TInt result=KErrNone;
1.330 + TInt c=iModules.Count();
1.331 + SModule* pM=(SModule*)&iModules[0];
1.332 + SModule* pE=pM+c;
1.333 + for (; pM<pE; ++pM)
1.334 + {
1.335 + pM->iDepList=(TInt*)Kern::Alloc(c*sizeof(TInt));
1.336 + if (!pM->iDepList)
1.337 + return KErrNoMemory;
1.338 + memset(pM->iDepList, 0xff, c*sizeof(TInt));
1.339 + Emulator::TModule etm((HINSTANCE)pM->iModuleHandle);
1.340 + const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
1.341 + __KTRACE_OPT(KDLL, Kern::Printf("Module %08x, imports=%08x flags=%08x", pM->iModuleHandle, imports, pM->iFlags));
1.342 + if (!imports || (pM->iFlags&EFlagAlwaysLoaded))
1.343 + continue;
1.344 +
1.345 + const SCapabilitySet& cap = pM->iS.iCaps;
1.346 + const SCapabilitySet& disabledCaps=*(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
1.347 +
1.348 + TInt* pI=pM->iDepList;
1.349 + for (; imports->Characteristics; ++imports )
1.350 + {
1.351 + Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
1.352 +
1.353 + if (!imp_etm.IsValid())
1.354 + continue; // spurious import
1.355 +
1.356 + if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
1.357 + continue; // not an epoc DLL
1.358 +
1.359 + TInt ix=Find((TInt)imp_etm.iModule);
1.360 + __ASSERT_ALWAYS(ix>=0, MM::Panic(MM::ECompileDepLists));
1.361 + *pI++=ix;
1.362 + __KTRACE_OPT(KDLL, Kern::Printf("Depends on %08x, ix=%d", imp_etm.iModule, ix));
1.363 +
1.364 + const SModule& dep = iModules[ix];
1.365 +
1.366 + SCapabilitySet missingCaps;
1.367 + SCapabilitySet depCaps = dep.iS.iCaps;
1.368 + TUint32 checkFail = 0;
1.369 + for (TInt i=0; i<SCapabilitySet::ENCapW; ++i)
1.370 + {
1.371 + depCaps[i] = dep.iS.iCaps[i]|disabledCaps[i];
1.372 + TUint32 missing = cap[i] & ~depCaps[i];
1.373 + missingCaps[i] = missing;
1.374 + checkFail |= missing;
1.375 + }
1.376 +
1.377 + __KTRACE_OPT(KDLL, Kern::Printf("Cap=%08x %08x, DepCap=%08x %08x", cap[1], cap[0], depCaps[1], depCaps[0]));
1.378 +
1.379 + if (checkFail)
1.380 + {
1.381 + TUint8 mainBuf8[MAX_PATH];
1.382 + TInt mainlen;
1.383 + {
1.384 + TUint16 mainBuf[MAX_PATH];
1.385 + mainlen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(pM->iModuleHandle),(LPWSTR)mainBuf);
1.386 + TruncToNarrow(mainBuf8, mainBuf, mainlen);
1.387 + }
1.388 + TPtrC mainp(mainBuf8,mainlen);
1.389 + TInt ix=mainp.LocateReverse('\\');
1.390 + if (ix>=0)
1.391 + mainp.Set(mainp.Mid(ix+1));
1.392 + if (mainp.Length() && mainp[mainp.Length()-1]==')' && (ix=mainp.LocateReverse('('))>=0)
1.393 + mainp.Set(mainp.Left(ix));
1.394 +
1.395 + TUint8 depBuf8[MAX_PATH];
1.396 + TInt deplen;
1.397 + {
1.398 + TUint16 depBuf[MAX_PATH];
1.399 + deplen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(dep.iModuleHandle),(LPWSTR)depBuf);
1.400 + TruncToNarrow(depBuf8, depBuf, deplen);
1.401 + }
1.402 + TPtrC depp(depBuf8,deplen);
1.403 + if ((ix=depp.LocateReverse('\\'))>=0)
1.404 + depp.Set(depp.Mid(ix+1));
1.405 +#ifndef __REMOVE_PLATSEC_DIAGNOSTICS__
1.406 + TInt r = PlatSec::LoaderCapabilityViolation(mainp, depp, missingCaps);
1.407 +#else //__REMOVE_PLATSEC_DIAGNOSTICS__
1.408 + TInt r = PlatSec::EmitDiagnostic();
1.409 +#endif // !__REMOVE_PLATSEC_DIAGNOSTICS__
1.410 + if(r!=KErrNone)
1.411 + result=r;
1.412 + }
1.413 + }
1.414 + }
1.415 + return result;
1.416 + }
1.417 +
1.418 +#ifdef __VC32__
1.419 +#pragma warning( default : 4701 ) // enable warning C4701: local variable 'missingCaps' may be used without having been initialized
1.420 +#endif
1.421 +
1.422 +void DModuleList::SetFlags()
1.423 + {
1.424 + __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::SetFlags"));
1.425 + TInt c=iModules.Count();
1.426 + SModule* pM=(SModule*)&iModules[0];
1.427 + SModule* pE=pM+c;
1.428 + for (; pM<pE; ++pM)
1.429 + {
1.430 + SModule* pM2=(SModule*)&iModules[0];
1.431 + for (; pM2<pE; ++pM2)
1.432 + pM2->iFlags &= ~EFlagMark;
1.433 + TUint32 flags=Flags(pM);
1.434 + if (flags & EFlagData)
1.435 + pM->iFlags|=EFlagDataPresent;
1.436 + if (flags & EFlagExe)
1.437 + pM->iFlags|=EFlagExeInTree;
1.438 + __KTRACE_OPT(KDLL, Kern::Printf("Module %08x Flags=%08x", pM->iModuleHandle, pM->iFlags));
1.439 + }
1.440 + pM=(SModule*)&iModules[0];
1.441 + for (; pM<pE; ++pM)
1.442 + {
1.443 + TInt dc=0;
1.444 + const TInt* pI=pM->iDepList;
1.445 + const TInt* pIE=pI+c;
1.446 + while (pI<pIE)
1.447 + {
1.448 + TInt ix=*pI++;
1.449 + if (ix<0)
1.450 + break;
1.451 + TUint32 mflags=iModules[ix].iFlags;
1.452 + if ( (mflags&(EFlagDataPresent|EFlagExeInTree)) && !(mflags&EFlagAlwaysLoaded))
1.453 + ++dc;
1.454 + }
1.455 + pM->iDepCount=dc;
1.456 + __KTRACE_OPT(KDLL, Kern::Printf("Module %08x DepCount=%d", pM->iModuleHandle, pM->iDepCount));
1.457 + }
1.458 + }
1.459 +
1.460 +TUint32 DModuleList::Flags(SModule* aM)
1.461 + {
1.462 + TUint32 flags=aM->iFlags;
1.463 + __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::Flags %08x", aM->iModuleHandle));
1.464 + if ((aM->iFlags & EFlagMark)==0)
1.465 + {
1.466 + aM->iFlags |= EFlagMark;
1.467 + const TInt* pI=aM->iDepList;
1.468 + const TInt* pE=pI+iModules.Count();
1.469 + while (pI<pE)
1.470 + {
1.471 + TInt ix=*pI++;
1.472 + if (ix<0)
1.473 + break;
1.474 + TUint32 mflags=Flags(&iModules[ix]);
1.475 + if (mflags&EFlagExe)
1.476 + mflags&=~EFlagData;
1.477 + flags |= mflags;
1.478 + }
1.479 + }
1.480 + __KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::Flags %08x = %08x", aM->iModuleHandle, flags));
1.481 + return flags;
1.482 + }
1.483 +
1.484 +TInt DModuleList::LoadDependencies()
1.485 + {
1.486 + __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LoadDependencies"));
1.487 + TInt c=iModules.Count();
1.488 + SModule* pM=(SModule*)&iModules[0];
1.489 + SModule* pE=pM+c;
1.490 + for (; pM<pE; ++pM)
1.491 + {
1.492 + DWin32CodeSeg* pS;
1.493 + TUint32 flags=pM->iFlags;
1.494 + __KTRACE_OPT(KDLL, Kern::Printf("ModuleHandle %08x flags %08x", pM->iModuleHandle, flags));
1.495 + if (!(flags & (EFlagDataPresent|EFlagExeInTree)) || (flags&EFlagAlwaysLoaded))
1.496 + continue;
1.497 + SWin32Module w32m;
1.498 + w32m.iWin32ModuleHandle=(TLinAddr)pM->iModuleHandle;
1.499 + w32m.iCodeSeg=NULL;
1.500 + TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
1.501 + __KTRACE_OPT(KDLL, Kern::Printf("GlobalIndex=%d", ix));
1.502 + if (ix<0 && (flags & EFlagExe))
1.503 + return KErrNotSupported; // we never implicitly load an EXE
1.504 + if (ix>=0)
1.505 + {
1.506 + pS=MM::Win32Modules[ix].iCodeSeg;
1.507 + __KTRACE_OPT(KDLL, Kern::Printf("Already loaded; CSEG=%08x %C", pS, pS));
1.508 + if (pS==iMain)
1.509 + {
1.510 + pS->iDepCount=pM->iDepCount;
1.511 + if (pS->iDepCount)
1.512 + {
1.513 + pS->iDeps=(DCodeSeg**)Kern::AllocZ(pS->iDepCount*sizeof(DCodeSeg*));
1.514 + if (!pS->iDeps)
1.515 + return KErrNoMemory;
1.516 + }
1.517 + }
1.518 + else
1.519 + {
1.520 + if (!(pS->iMark & DCodeSeg::EMarkLdr))
1.521 + {
1.522 + pS->iMark |= DCodeSeg::EMarkLdr;
1.523 + pS->CheckedOpen();
1.524 + }
1.525 + pM->iFlags|=EFlagAlreadyLoaded;
1.526 + }
1.527 + pM->iCodeSeg=pS;
1.528 + continue;
1.529 + }
1.530 + __KTRACE_OPT(KDLL, Kern::Printf("Create new, depcount=%d", pM->iDepCount));
1.531 + pS=new DWin32CodeSeg;
1.532 + if (!pS)
1.533 + return KErrNoMemory;
1.534 + TInt r=pS->CreateAlreadyLoaded((HMODULE)pM->iModuleHandle, pM->iDepCount);
1.535 + if (r!=KErrNone)
1.536 + {
1.537 + delete pS;
1.538 + return r;
1.539 + }
1.540 + pM->iCodeSeg=pS;
1.541 + pS->iS = pM->iS;
1.542 + pS->iModuleVersion = pM->iModuleVersion;
1.543 + if (iMain->iAttr & ECodeSegAttKernel)
1.544 + pS->iAttr |= ECodeSegAttKernel;
1.545 + if (flags & EFlagData)
1.546 + {
1.547 + pS->iMark |= DCodeSeg::EMarkData|DCodeSeg::EMarkDataPresent;
1.548 + if (!(flags&EFlagExe))
1.549 + pS->iMark |= DCodeSeg::EMarkDataInit;
1.550 + }
1.551 + if ( (flags & EFlagData) || ((flags&(EFlagExe|EFlagExeInTree))==EFlagExeInTree) )
1.552 + {
1.553 + if (iAttachProcess)
1.554 + {
1.555 + pS->iExeCodeSeg = iAttachProcess->CodeSeg();
1.556 + pS->SetAttachProcess(iAttachProcess);
1.557 + }
1.558 + }
1.559 + }
1.560 + return KErrNone;
1.561 + }
1.562 +
1.563 +void DModuleList::LinkDependencies()
1.564 + {
1.565 + __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LinkDependencies"));
1.566 + TInt c=iModules.Count();
1.567 + SModule* pM=(SModule*)&iModules[0];
1.568 + SModule* pE=pM+c;
1.569 + for (; pM<pE; ++pM)
1.570 + {
1.571 + DWin32CodeSeg* pS=pM->iCodeSeg;
1.572 + if (!pS || (pM->iFlags&EFlagAlreadyLoaded))
1.573 + continue;
1.574 + const TInt* pI=pM->iDepList;
1.575 + const TInt* pIE=pI+c;
1.576 + while (pI<pIE)
1.577 + {
1.578 + TInt ix=*pI++;
1.579 + if (ix<0)
1.580 + break;
1.581 + DWin32CodeSeg* pD=iModules[ix].iCodeSeg;
1.582 + if (pD)
1.583 + pS->iDeps[pS->iNextDep++]=pD;
1.584 + }
1.585 + }
1.586 + pM=(SModule*)&iModules[0];
1.587 + }
1.588 +
1.589 +TInt DModuleList::Loaded()
1.590 + {
1.591 + __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::Loaded()"));
1.592 + TInt c=iModules.Count();
1.593 + SModule* pM=(SModule*)&iModules[0];
1.594 + SModule* pE=pM+c;
1.595 + TInt r=KErrNone;
1.596 + for (; pM<pE && r==KErrNone; ++pM)
1.597 + {
1.598 + DWin32CodeSeg* pS=pM->iCodeSeg;
1.599 + if (pS && pS!=iMain)
1.600 + {
1.601 + pS->FinaliseRecursiveFlags();
1.602 + pS->iMark |= DCodeSeg::EMarkLoaded;
1.603 + }
1.604 + }
1.605 + if (r==KErrNone)
1.606 + {
1.607 + pM=(SModule*)&iModules[0];
1.608 + for (; pM<pE; ++pM)
1.609 + pM->iCodeSeg=NULL; // cleanup will occur by EMarkLdr if needed
1.610 + }
1.611 + return r;
1.612 + }
1.613 +
1.614 +TInt MakeDll(HANDLE aFile)
1.615 + {
1.616 + IMAGE_DOS_HEADER dosh;
1.617 + DWORD bytes;
1.618 + ReadFile(aFile, &dosh, sizeof(dosh), &bytes, NULL);
1.619 + if ( IMAGE_DOS_SIGNATURE != dosh.e_magic )
1.620 + return KErrArgument;
1.621 + if (dosh.e_lfarlc < sizeof(dosh))
1.622 + return KErrArgument;
1.623 + SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
1.624 + IMAGE_NT_HEADERS32 peh;
1.625 + ReadFile(aFile, &peh, sizeof(peh), &bytes, NULL);
1.626 + if ( peh.Signature != IMAGE_NT_SIGNATURE )
1.627 + return KErrArgument;
1.628 +
1.629 + peh.FileHeader.Characteristics |= IMAGE_FILE_DLL;
1.630 + peh.OptionalHeader.AddressOfEntryPoint = 0;
1.631 + SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
1.632 + WriteFile(aFile, &peh, sizeof(peh), &bytes, NULL);
1.633 + return KErrNone;
1.634 + }
1.635 +
1.636 +wchar_t* TempModuleName(const wchar_t* aExe)
1.637 + {
1.638 + static TInt ModuleGeneration = 0;
1.639 + static TInt Time = 0;
1.640 +
1.641 + WCHAR ex_[KMaxFileName + 1];
1.642 +
1.643 + if (!Time)
1.644 + {
1.645 + SYSTEMTIME st;
1.646 + GetSystemTime(&st);
1.647 + Time = st.wSecond + st.wMinute*60 + st.wHour*3600;
1.648 + }
1.649 +
1.650 + const char* imagePath = Property::GetString("EmulatorImagePath");
1.651 + WCHAR* p = ex_;
1.652 + while ((*p++ = *imagePath++) != 0)
1.653 + ;
1.654 + wcscpy(p-1, wcsrchr(aExe, '\\') + 1);
1.655 + p = ex_ + wcslen(ex_);
1.656 + *p++ = '(';
1.657 + _itow(Time, p, 36);
1.658 + p += wcslen(p);
1.659 + *p++ = '-';
1.660 + _itow(ModuleGeneration++, p, 10);
1.661 + p += wcslen(p);
1.662 + *p++ = ')';
1.663 + *p++ = '\0';
1.664 + wchar_t* file = (wchar_t*)Kern::Alloc((p-ex_)*sizeof(WCHAR));
1.665 + if (file)
1.666 + wcscpy(file, ex_);
1.667 + return file;
1.668 + }
1.669 +
1.670 +DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&)
1.671 +//
1.672 +// Create a new instance of this class.
1.673 +//
1.674 + {
1.675 +
1.676 + __KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg"));
1.677 + return new DWin32CodeSeg;
1.678 + }
1.679 +
1.680 +DWin32CodeSeg::DWin32CodeSeg()
1.681 +//
1.682 +// Constructor
1.683 +//
1.684 + {
1.685 + }
1.686 +
1.687 +DWin32CodeSeg::~DWin32CodeSeg()
1.688 +//
1.689 +// Destructor
1.690 +//
1.691 + {
1.692 + __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Destruct %C", this));
1.693 + DBase::Delete(iModuleList);
1.694 + if (iWinInstance)
1.695 + {
1.696 + DCodeSeg::Wait();
1.697 + SWin32Module w32m;
1.698 + w32m.iWin32ModuleHandle=(TLinAddr)iModuleHandle;
1.699 + w32m.iCodeSeg=NULL;
1.700 + TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
1.701 + if (ix>=0)
1.702 + {
1.703 + if (iAlwaysLoaded)
1.704 + MM::Win32Modules[ix].iCodeSeg=NULL;
1.705 + else
1.706 + MM::Win32Modules.Remove(ix);
1.707 + }
1.708 + // Kernel process has to be told to unmap code seg to work round
1.709 + // a problem where failed driver code seg is not unmapped before delete
1.710 + K::TheKernelProcess->UnmapCodeSeg(this);
1.711 + Emulator::FreeLibrary(iWinInstance);
1.712 + DCodeSeg::Signal();
1.713 + }
1.714 + if (iModuleFile)
1.715 + {
1.716 + Emulator::DeleteFile(iModuleFile);
1.717 + Kern::Free(iModuleFile);
1.718 + }
1.719 + Kern::Free(iDataCopy);
1.720 + DCodeSeg::Destruct();
1.721 + }
1.722 +
1.723 +TInt DWin32CodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
1.724 + {
1.725 + __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::DoCreate %C proc %O", this, aProcess));
1.726 +
1.727 + TBool exe=(iExeCodeSeg==this);
1.728 + if (exe && (iAttr&ECodeSegAttKernel))
1.729 + {
1.730 + // loading EKERN.EXE
1.731 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN"));
1.732 + TUint16 fileNameW[KMaxFileName];
1.733 + ExpandToWide(fileNameW, iFileName->Ptr(), iFileName->Length());
1.734 + fileNameW[iFileName->Length()] = '\0';
1.735 + iWinInstance = Emulator::LoadLibrary((LPCWSTR)fileNameW);
1.736 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN %08x", iWinInstance));
1.737 + if (!iWinInstance)
1.738 + return KErrGeneral;
1.739 + if (aInfo.iTotalDataSize)
1.740 + iMark|=EMarkData|EMarkDataPresent;
1.741 + KernelCodeSeg=this;
1.742 + KernelModuleHandle=Emulator::GetModuleHandle((LPCWSTR)fileNameW);
1.743 + return RegisterCodeSeg(KernelModuleHandle);
1.744 + }
1.745 + TWin32Filename w32fn(*iFileName);
1.746 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : w32fn=%S",iFileName))
1.747 + DWin32Process* p=(DWin32Process*)aProcess;
1.748 + TInt r=KErrNone;
1.749 + DCodeSeg::Wait();
1.750 + HMODULE h = Emulator::GetModuleHandle(w32fn);
1.751 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : h=%08x exe=%08x",h,exe));
1.752 + if (h && exe)
1.753 + {
1.754 + if (h == GetModuleHandleA(NULL))
1.755 + {
1.756 + // This was the executable that was used to run the emulator
1.757 + // so all relocations will be valid and we can use it
1.758 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : initial exe"));
1.759 + if (BootComplete)
1.760 + goto makecopy; // we can only do this once however
1.761 + iWinInstance = Emulator::LoadLibrary(w32fn);
1.762 + BootComplete = ETrue;
1.763 + }
1.764 + else
1.765 + r=KErrAlreadyExists; // can't load same EXEXP twice
1.766 + }
1.767 + else if (h)
1.768 + {
1.769 + // Already loaded DLL
1.770 + // Code segment doesn't exist so create it
1.771 + __KTRACE_OPT(KDLL,Kern::Printf("Already loaded, module %08x",h));
1.772 + iWinInstance = Emulator::LoadLibrary(w32fn);
1.773 + }
1.774 + else if (iAttr & ECodeSegAttHDll)
1.775 + {
1.776 + // EXE with exports (EXEXP target) - can only have one instance
1.777 + // or DLL not already loaded
1.778 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EXEXP or new DLL"));
1.779 + iWinInstance = Emulator::LoadLibrary(w32fn);
1.780 + if (iWinInstance)
1.781 + h=Emulator::GetModuleHandle(w32fn);
1.782 + }
1.783 + else
1.784 + {
1.785 + // EXE with no exports. In order that multiple instances of the EXE may be run,
1.786 + // we make a copy of the EXE file to a name which is unique across instances,
1.787 + // set the DLL flag and load it as a DLL.
1.788 +makecopy:
1.789 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : MakeCopy"));
1.790 + h=0;
1.791 + iModuleFile = TempModuleName(w32fn);
1.792 + if (!iModuleFile)
1.793 + r=KErrNoMemory;
1.794 + else if (Emulator::CopyFile(w32fn,iModuleFile,FALSE))
1.795 + {
1.796 + DWORD fattr = Emulator::GetFileAttributes(iModuleFile);
1.797 + if (fattr != 0xffffffff && Emulator::SetFileAttributes(iModuleFile, fattr & ~FILE_ATTRIBUTE_READONLY))
1.798 + {
1.799 + HANDLE f = Emulator::CreateFile(iModuleFile,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL);
1.800 + if (INVALID_HANDLE_VALUE != f)
1.801 + {
1.802 + r = MakeDll(f);
1.803 + CloseHandle(f);
1.804 + if (r==KErrNone)
1.805 + {
1.806 + iWinInstance = Emulator::LoadLibrary(iModuleFile);
1.807 + if (iWinInstance)
1.808 + h=Emulator::GetModuleHandle(iModuleFile);
1.809 + }
1.810 + }
1.811 + }
1.812 + }
1.813 + }
1.814 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d iWinInstance=%08x",__LINE__,r,iWinInstance));
1.815 + if (r==KErrNone && !iWinInstance)
1.816 + r=Emulator::LastError();
1.817 + __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d",__LINE__,r));
1.818 + if (r==KErrNone)
1.819 + {
1.820 + const char* entry_name = exe ? "_E32Startup" : "_E32Dll" ;
1.821 + aInfo.iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, entry_name);
1.822 + if (!aInfo.iFileEntryPoint)
1.823 + {
1.824 + r=KErrNotSupported;
1.825 + }
1.826 + else
1.827 + {
1.828 + r=RegisterCodeSeg(h);
1.829 + }
1.830 +
1.831 + if (r == KErrNone)
1.832 + {
1.833 + r = CopyDataBss();
1.834 + }
1.835 + }
1.836 + if (r==KErrNone && aInfo.iTotalDataSize && !iAlwaysLoaded)
1.837 + {
1.838 + iMark|=EMarkData|EMarkDataPresent;
1.839 + if (!exe)
1.840 + iMark|=EMarkDataInit;
1.841 + }
1.842 +
1.843 + if (r==KErrNone)
1.844 + r=ProcessImports(p);
1.845 + __KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
1.846 + DCodeSeg::Signal();
1.847 + return r;
1.848 + }
1.849 +
1.850 +TInt DWin32CodeSeg::RegisterCodeSeg(HMODULE aModule)
1.851 + {
1.852 + __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %C RegisterCodeSeg(%08x)", this, aModule));
1.853 + Emulator::TModule etm(aModule);
1.854 + const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
1.855 + iRunAddress = (TLinAddr)aModule;
1.856 + iSize = nth->OptionalHeader.SizeOfImage;
1.857 + SWin32Module w32m;
1.858 + w32m.iWin32ModuleHandle=(TLinAddr)aModule;
1.859 + w32m.iCodeSeg=this;
1.860 + TInt r=KErrNone;
1.861 + TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
1.862 + if (ix>=0)
1.863 + {
1.864 + SWin32Module& wmr=MM::Win32Modules[ix];
1.865 + __ASSERT_ALWAYS(!wmr.iCodeSeg, MM::Panic(MM::EInvalidSharedModule));
1.866 + wmr.iCodeSeg=this;
1.867 + iAlwaysLoaded=ETrue;
1.868 + }
1.869 + else
1.870 + r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
1.871 + if (r==KErrNone)
1.872 + {
1.873 + iModuleHandle=aModule;
1.874 + iCodeSegId=++MM::NextCodeSegId;
1.875 + }
1.876 + return r;
1.877 + }
1.878 +
1.879 +TInt DWin32CodeSeg::CreateAlreadyLoaded(HMODULE aModule, TInt aDepCount)
1.880 + {
1.881 + __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %08x CreateAlreadyLoaded(%08x,%d)", this, aModule, aDepCount));
1.882 + Emulator::TModule etm(aModule);
1.883 + etm.GetUids(iUids);
1.884 + TInt32 uid1=iUids.iUid[0].iUid;
1.885 + if (uid1!=KDynamicLibraryUidValue) // only implicitly load DLLs
1.886 + return KErrNotSupported;
1.887 +
1.888 + WCHAR name[MAX_PATH+1];
1.889 + TInt r=Emulator::GetModuleFileName(aModule, name);
1.890 + if (!r)
1.891 + return Emulator::LastError();
1.892 + TUint8 name8[MAX_PATH+1];
1.893 + TruncToNarrow(name8,(const TUint16*)name,-1);
1.894 +
1.895 + //SL:
1.896 + __KTRACE_OPT(KDLL, Kern::Printf("Loading library %s", name8));
1.897 +
1.898 + TPtrC fpptr((const TText*)name8);
1.899 + TInt slash=fpptr.LocateReverse('\\');
1.900 + TPtrC nptr=fpptr.Mid(slash+1);
1.901 + iFileName=HBuf::New(nptr);
1.902 + if (!iFileName)
1.903 + return KErrNoMemory;
1.904 + iRootName.Set(*iFileName);
1.905 + iExtOffset = iFileName->LocateReverse('.');
1.906 + if (iExtOffset==KErrNotFound)
1.907 + iExtOffset = iFileName->Length();
1.908 + iModuleVersion = 0x00010000u;
1.909 + iDepCount=aDepCount;
1.910 + if (iDepCount)
1.911 + {
1.912 + iDeps=(DCodeSeg**)Kern::AllocZ(iDepCount*sizeof(DCodeSeg*));
1.913 + if (!iDeps)
1.914 + return KErrNoMemory;
1.915 + }
1.916 + iWinInstance = Emulator::LoadLibrary(name);
1.917 + if (!iWinInstance)
1.918 + return Emulator::LastError();
1.919 + iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, "_E32Dll");
1.920 + if (!iFileEntryPoint)
1.921 + return KErrNotSupported;
1.922 + iEntryPtVeneer = iFileEntryPoint;
1.923 + r=RegisterCodeSeg(aModule);
1.924 + if (r == KErrNone)
1.925 + r = CopyDataBss();
1.926 + if (r == KErrNone)
1.927 + r = CodeSegsByName.InsertInOrderAllowRepeats(this, &CompareCodeSegsByName);
1.928 + if (r == KErrNone)
1.929 + r = CodeSegsByAddress.Add(this);
1.930 + if (r==KErrNone)
1.931 + {
1.932 + GlobalList.Add(&iLink);
1.933 + iAsyncDeleteNext=this;
1.934 + }
1.935 + __KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
1.936 + return r;
1.937 + }
1.938 +
1.939 +TInt DWin32CodeSeg::CopyDataBss()
1.940 + {
1.941 + __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::CopyDataBss()"));
1.942 +
1.943 + Emulator::TModule etm(iModuleHandle);
1.944 + const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
1.945 + if (!(hdr->iFlags & KEmulatorImageFlagAllowDllData))
1.946 + return KErrNone;
1.947 + const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
1.948 + const IMAGE_SECTION_HEADER* bss=etm.SectionHeader(KWin32SectionName_EpocBss);
1.949 + if (data)
1.950 + {
1.951 + iRealDataSize = data->Misc.VirtualSize;
1.952 + iDataDest = (TLinAddr)etm.Translate(data->VirtualAddress);
1.953 + iDataCopy = Kern::Alloc(iRealDataSize);
1.954 + if (!iDataCopy)
1.955 + return KErrNoMemory;
1.956 + memcpy(iDataCopy, (const TAny*)iDataDest, iRealDataSize);
1.957 + }
1.958 + if (bss)
1.959 + {
1.960 + iRealBssSize = bss->Misc.VirtualSize;
1.961 + iBssDest = (TLinAddr)etm.Translate(bss->VirtualAddress);
1.962 + }
1.963 + return KErrNone;
1.964 + }
1.965 +
1.966 +TInt DWin32CodeSeg::ProcessImports(DProcess* aProcess)
1.967 + {
1.968 + __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::ProcessImports(%O)", aProcess));
1.969 + iModuleList=new DModuleList(this, aProcess);
1.970 + if (!iModuleList)
1.971 + return KErrNoMemory;
1.972 + TInt r=iModuleList->GatherDependencies(iModuleHandle);
1.973 + if (r!=KErrNone)
1.974 + return r;
1.975 + TInt ix=iModuleList->Find((TInt)iModuleHandle);
1.976 + DModuleList::SModule& mm=iModuleList->iModules[ix];
1.977 + r=iModuleList->CompileDepLists();
1.978 + if (r==KErrNone)
1.979 + {
1.980 + iModuleList->SetFlags();
1.981 + r=iModuleList->LoadDependencies();
1.982 + if (r==KErrNone)
1.983 + {
1.984 + if ((mm.iFlags&(DModuleList::EFlagDataPresent|DModuleList::EFlagExeInTree)) && !(mm.iFlags&DModuleList::EFlagAlwaysLoaded))
1.985 + {
1.986 + if (aProcess)
1.987 + {
1.988 + iExeCodeSeg=aProcess->CodeSeg();
1.989 + SetAttachProcess(aProcess);
1.990 + }
1.991 + }
1.992 + iModuleList->LinkDependencies();
1.993 + }
1.994 + }
1.995 + return r;
1.996 + }
1.997 +
1.998 +TInt DWin32CodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
1.999 + {
1.1000 + __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded()"));
1.1001 + TInt r=KErrNone;
1.1002 + if (iModuleList)
1.1003 + {
1.1004 + r=iModuleList->Loaded();
1.1005 + if (r==KErrNone)
1.1006 + {
1.1007 + DBase::Delete(iModuleList);
1.1008 + iModuleList=NULL;
1.1009 + }
1.1010 + }
1.1011 + if (r==KErrNone)
1.1012 + r=DCodeSeg::Loaded(aInfo);
1.1013 + __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded() - %d", r));
1.1014 + return r;
1.1015 + }
1.1016 +
1.1017 +void DWin32CodeSeg::ReadExportDir(TUint32*)
1.1018 + {
1.1019 + // not needed
1.1020 + }
1.1021 +
1.1022 +TBool DWin32CodeSeg::FindCheck(DProcess* /*aProcess*/)
1.1023 + {
1.1024 + // We never create multiple copies of the same code segment,
1.1025 + // so if code segment exists, allow it to be found.
1.1026 + // CodeSegOpen will fail if it is incompatible.
1.1027 + return ETrue;
1.1028 + }
1.1029 +
1.1030 +TBool DWin32CodeSeg::OpenCheck(DProcess* aProcess)
1.1031 + {
1.1032 + __KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess));
1.1033 + if (!aProcess)
1.1034 + return EFalse; // never reuse EXE code segments
1.1035 + return ETrue;
1.1036 + }
1.1037 +
1.1038 +TLibraryFunction DWin32CodeSeg::Lookup(TInt aOrdinal)
1.1039 +//
1.1040 +// Find an exported function by ordinal
1.1041 +//
1.1042 + {
1.1043 + TLibraryFunction f = NULL;
1.1044 + if (aOrdinal != 0)
1.1045 + {
1.1046 +
1.1047 + f = (TLibraryFunction)Emulator::GetProcAddress(iWinInstance, (const char *)aOrdinal);
1.1048 + if ((TLinAddr)f == iFileEntryPoint)
1.1049 + f = NULL;
1.1050 + }
1.1051 + else
1.1052 + {
1.1053 + // Find 0th Ordinal, which should be named symbol export data, from named data segment
1.1054 + Emulator::TModule etm(iModuleHandle);
1.1055 + f = (TLibraryFunction)etm.Section(KWin32SectionName_NmdExpData);
1.1056 + }
1.1057 + __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Lookup(%d)->%08x",aOrdinal,f));
1.1058 + return f;
1.1059 + }
1.1060 +
1.1061 +DCodeSeg* DCodeSeg::FindRomCode(const TAny*)
1.1062 + {
1.1063 + // never used
1.1064 + return NULL;
1.1065 + }
1.1066 +
1.1067 +void DWin32CodeSeg::InitData()
1.1068 + {
1.1069 + }
1.1070 +
1.1071 +TInt DWin32CodeSeg::GetMemoryInfo(TModuleMemoryInfo&, DProcess*)
1.1072 + {
1.1073 + return KErrNotSupported;
1.1074 + }
1.1075 +
1.1076 +void DWin32CodeSeg::Info(TCodeSegCreateInfo& aInfo)
1.1077 + {
1.1078 + Emulator::TModule etm(iModuleHandle);
1.1079 + const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
1.1080 + const IMAGE_EXPORT_DIRECTORY* exd=
1.1081 + (const IMAGE_EXPORT_DIRECTORY*)etm.Translate(nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
1.1082 + const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
1.1083 + TBool isExe = hdr && hdr->iUids[0].iUid==KExecutableImageUidValue;
1.1084 + const IMAGE_SECTION_HEADER* text=etm.SectionHeader(KWin32SectionName_Text);
1.1085 + const IMAGE_SECTION_HEADER* rdata=etm.SectionHeader(KWin32SectionName_RData);
1.1086 + const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
1.1087 + if (!isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
1.1088 + data = NULL;
1.1089 + aInfo.iTextSize=text->Misc.VirtualSize;
1.1090 + aInfo.iCodeSize=text->Misc.VirtualSize;
1.1091 + if (rdata)
1.1092 + aInfo.iCodeSize+=rdata->Misc.VirtualSize;
1.1093 + aInfo.iDataSize=data ? (data->SizeOfRawData) : 0;
1.1094 + aInfo.iBssSize=data ? (data->Misc.VirtualSize-data->SizeOfRawData) : 0;
1.1095 + aInfo.iTotalDataSize=aInfo.iDataSize+aInfo.iBssSize;
1.1096 + aInfo.iExportDir=(TLinAddr)exd;
1.1097 + aInfo.iExportDirCount=exd ? exd->NumberOfFunctions : 0;
1.1098 + aInfo.iCodeLoadAddress=(TLinAddr)etm.Translate(text->VirtualAddress);
1.1099 + aInfo.iCodeRunAddress=aInfo.iCodeLoadAddress;
1.1100 + aInfo.iDataLoadAddress=data ? (TLinAddr)etm.Translate(data->VirtualAddress) : 0;
1.1101 + aInfo.iDataRunAddress=aInfo.iDataLoadAddress;
1.1102 + DCodeSeg::Info(aInfo);
1.1103 + }
1.1104 +
1.1105 +TLinAddr DCodeSeg::ExceptionDescriptor()
1.1106 + {
1.1107 + return 0; // not used on emulator
1.1108 + }
1.1109 +
1.1110 +TInt MM::RegisterModule(HMODULE aModule)
1.1111 + {
1.1112 + __KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule %08x",aModule));
1.1113 + SWin32Module w32m;
1.1114 + w32m.iWin32ModuleHandle=(TLinAddr)aModule;
1.1115 + w32m.iCodeSeg=NULL;
1.1116 + TInt r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
1.1117 + __KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule ret %d",r));
1.1118 + return r;
1.1119 + }
1.1120 +
1.1121 +_LIT(KRomSysBin, "Z:\\sys\\bin");
1.1122 +
1.1123 +// Massage file names returned for stuff in EPOCROOT\epoc32\release\wins\xxxx\
1.1124 +// in order to make them appear to be in z:\system\libs
1.1125 +void P::NormalizeExecutableFileName(TDes& a)
1.1126 + {
1.1127 + __KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName %lS", &a));
1.1128 + if (a.Length()<3 || a[1]!=':' || a[2]!='\\')
1.1129 + {
1.1130 + // don't have a drive so assume in 'ROM'
1.1131 + TFileName initial(a);
1.1132 + a=KRomSysBin();
1.1133 + if (initial.Length()==0 || initial[0]!='\\')
1.1134 + a.Append('\\');
1.1135 + a+=initial;
1.1136 + __KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName -> %lS", &a));
1.1137 + }
1.1138 + }
1.1139 +
1.1140 +TInt LookupDllUid(TInt aModule)
1.1141 + {
1.1142 + TInt r = KDllUid_Default;
1.1143 + Kern::AccessCode();
1.1144 + SWin32Module w32m;
1.1145 + w32m.iWin32ModuleHandle=(TLinAddr)aModule;
1.1146 + TInt ix;
1.1147 + MM::Win32Modules.SpecificFindInUnsignedKeyOrder(w32m, ix, EArrayFindMode_Last);
1.1148 + if (ix>0)
1.1149 + {
1.1150 + DWin32CodeSeg* pS = MM::Win32Modules[ix-1].iCodeSeg;
1.1151 + if (pS && pS->iFileEntryPoint==(TLinAddr)aModule)
1.1152 + r = pS->iCodeSegId;
1.1153 + }
1.1154 + Kern::EndAccessCode();
1.1155 + return r;
1.1156 + }
1.1157 +
1.1158 +