sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\memmodel\emul\win32\mcodeseg.cpp sl@0: // sl@0: // sl@0: sl@0: #define __INCLUDE_ALL_SUPPORTED_CAPABILITIES__ sl@0: #include "memmodel.h" sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #define __CHECKHEAP() ((RHeapK*)K::Allocator)->Check() sl@0: sl@0: static TBool BootComplete; // flag set when boot EXE is loaded as an EPOC process sl@0: static DWin32CodeSeg* KernelCodeSeg; sl@0: static HMODULE KernelModuleHandle; sl@0: sl@0: GLREF_C TInt CompareCodeSegsByName(const DCodeSeg& aA, const DCodeSeg& aB); sl@0: sl@0: void TruncToNarrow(TUint8* aDes, const TUint16* aSrc, int aLen) sl@0: { sl@0: //converts to narrow by dumping the high order byte sl@0: if(aDes && aSrc) sl@0: { sl@0: if(aLen==-1) sl@0: { sl@0: for(int index=0;*aSrc;index++) sl@0: *aDes++ = (TUint8)*aSrc++; sl@0: *aDes = '\0'; sl@0: } sl@0: else sl@0: for(int index=0;indexiFastExecTable; sl@0: const SSlowExecEntry* slow = nthrd->iSlowExecTable; sl@0: nthrd->iFastExecTable = (SFastExecTable*)&DummyFastExecTable; sl@0: nthrd->iSlowExecTable = DummySlowExecTable.iEntries; sl@0: TLibraryEntry ep = (TLibraryEntry)aEntryPoint; sl@0: (*ep)(KModuleEntryReasonProcessAttach); sl@0: nthrd->iFastExecTable = fast; sl@0: nthrd->iSlowExecTable = slow; sl@0: NKern::Unlock(); sl@0: } sl@0: sl@0: class TWin32Filename sl@0: { sl@0: public: sl@0: inline TWin32Filename() sl@0: {iBuf[0] = '\0';} sl@0: inline TWin32Filename(const TDesC& aFilename) sl@0: {Set(aFilename);} sl@0: inline TWin32Filename& operator=(const TDesC& aFilename) sl@0: {Set(aFilename);return *this;} sl@0: inline operator LPCWSTR() const sl@0: {return iBuf;} sl@0: private: sl@0: void Set(const TDesC& aFilename); sl@0: private: sl@0: WCHAR iBuf[KMaxFileName + 1]; sl@0: }; sl@0: sl@0: void TWin32Filename::Set(const TDesC& aFilename) sl@0: { sl@0: TUint16 fileName[KMaxFileName]; sl@0: ExpandToWide(fileName, aFilename.Ptr(), aFilename.Length()); sl@0: TPtr p((TUint8*)iBuf,KMaxFileName<<1); sl@0: Property::MapFilename(p, TPtrC((TUint8*)fileName,aFilename.Length()<<1)); sl@0: iBuf[p.Length()>>1] = '\0'; sl@0: } sl@0: sl@0: class DModuleList : public DBase sl@0: { sl@0: public: sl@0: enum TFlags sl@0: { sl@0: EFlagData=0x01, sl@0: EFlagDataPresent=0x02, sl@0: EFlagAlreadyLoaded=0x04, sl@0: EFlagMark=0x08, sl@0: EFlagExe=0x10, sl@0: EFlagAlwaysLoaded=0x20, sl@0: EFlagExeInTree=0x40, sl@0: }; sl@0: sl@0: struct SModule sl@0: { sl@0: TLinAddr iModuleHandle; sl@0: DWin32CodeSeg* iCodeSeg; sl@0: TUint32 iFlags; sl@0: SSecurityInfo iS; sl@0: TUint32 iModuleVersion; sl@0: TInt iDepCount; sl@0: TInt* iDepList; sl@0: }; sl@0: public: sl@0: DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess); sl@0: virtual ~DModuleList(); sl@0: TInt Find(TInt aModule); sl@0: TInt GatherDependencies(HMODULE aModule); sl@0: TInt CompileDepLists(); sl@0: void SetFlags(); sl@0: TUint32 Flags(SModule* aM); sl@0: TInt LoadDependencies(); sl@0: void LinkDependencies(); sl@0: TInt Loaded(); sl@0: public: sl@0: DWin32CodeSeg* iMain; sl@0: DProcess* iAttachProcess; sl@0: RArray iModules; sl@0: }; sl@0: sl@0: DModuleList::DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess) sl@0: : iMain(aMainSeg), iAttachProcess(aProcess), sl@0: iModules(8, _FOFF(SModule,iModuleHandle), 2*256) sl@0: { sl@0: } sl@0: sl@0: DModuleList::~DModuleList() sl@0: { sl@0: TInt c = iModules.Count(); sl@0: if (c) sl@0: { sl@0: SModule* pM = (SModule*)&iModules[0]; sl@0: SModule* pE = pM + c; sl@0: for (; pMiDepList); sl@0: } sl@0: } sl@0: iModules.Close(); sl@0: } sl@0: sl@0: TInt DModuleList::Find(TInt aModule) sl@0: { sl@0: SModule mod; sl@0: mod.iModuleHandle=(TLinAddr)aModule; sl@0: return iModules.FindInUnsignedKeyOrder(mod); sl@0: } sl@0: /** sl@0: Populate iModules with SModule entries corresponding to supplied HModule and all of its dependencies, sl@0: direct and indirect. sl@0: sl@0: @param aModule A Windows module handle sl@0: @return KErrNone if successful sl@0: */ sl@0: TInt DModuleList::GatherDependencies(HMODULE aModule) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain)); sl@0: Emulator::TModule etm(aModule); sl@0: SModule mod; sl@0: mod.iModuleHandle=(TLinAddr)aModule; sl@0: mod.iCodeSeg=NULL; sl@0: mod.iDepList=NULL; sl@0: sl@0: TUint32 uid[3]; sl@0: TUidType& uidref=*(TUidType*)uid; sl@0: const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian); sl@0: if (!hdr) sl@0: return KErrNotSupported; sl@0: __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)); sl@0: mod.iS = hdr->iS; sl@0: // Overide capabilities in image sl@0: const SCapabilitySet& disabledCaps = *(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities; sl@0: for(TInt i=0; iiModuleVersion; sl@0: mod.iFlags = (hdr->iFlags & KEmulatorImageFlagAllowDllData) ? EFlagData|EFlagDataPresent : 0; sl@0: uidref = *(const TUidType*)&hdr->iUids[0]; sl@0: TBool isExe = (uid[0]==KExecutableImageUidValue); sl@0: TBool data_section_present = (etm.Section(KWin32SectionName_EpocData) != NULL); sl@0: if (data_section_present && isExe) sl@0: mod.iFlags = EFlagData|EFlagDataPresent; sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DataSectionPresent = %x", data_section_present)); sl@0: sl@0: // Can't do this for CodeWarrior since it sticks everything in .data, even constants sl@0: // On VC6 this check works for Base code, but not for some other code. sl@0: // if (data_section_present && !isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData)) sl@0: // return KErrNotSupported; sl@0: sl@0: if (!data_section_present) sl@0: mod.iFlags = 0; sl@0: if (isExe) sl@0: mod.iFlags |= EFlagExe|EFlagExeInTree; sl@0: sl@0: SWin32Module w32m; sl@0: w32m.iWin32ModuleHandle=(TLinAddr)aModule; sl@0: w32m.iCodeSeg=NULL; sl@0: TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m); sl@0: __KTRACE_OPT(KDLL, Kern::Printf("GlobalIx=%d", ix)); sl@0: if ((ix>=0 && !MM::Win32Modules[ix].iCodeSeg) || aModule==KernelModuleHandle) sl@0: mod.iFlags|=EFlagAlwaysLoaded; sl@0: TInt r=iModules.InsertInUnsignedKeyOrder(mod); sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Flags=%08x, InsertRes=%d", mod.iFlags, r)); sl@0: if (r==KErrAlreadyExists) sl@0: return KErrNone; sl@0: if (r!=KErrNone) sl@0: return r; sl@0: if (mod.iFlags & EFlagAlwaysLoaded) sl@0: return KErrNone; // stop if we reach an extension or variant sl@0: if (data_section_present && (mod.iFlags & EFlagData)==0) sl@0: { sl@0: // DLL, .data present but 'epocallowdlldata' not specified sl@0: // - either the compiler forgetting that something's constant or sl@0: // developer forgetting to specify 'epocallowdlldata'. sl@0: // call entry point from here to keep the compiler happy sl@0: const char* entry_name = "_E32Dll" ; sl@0: TLinAddr ep = (TLinAddr)Emulator::GetProcAddress(aModule, entry_name); sl@0: __NK_ASSERT_ALWAYS(ep!=0); sl@0: ForceEntryPointCall(ep); sl@0: } sl@0: sl@0: const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports(); sl@0: if (imports) sl@0: { sl@0: for (; imports->Characteristics; ++imports ) sl@0: { sl@0: __KTRACE_OPT(KDLL, { TPtrC8 n((const TText8*)etm.Translate(imports->Name)); Kern::Printf("Importing from %S", &n);} ); sl@0: Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name)); sl@0: sl@0: if (!imp_etm.IsValid()) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Spurious import")); sl@0: continue; sl@0: } sl@0: sl@0: if (imp_etm.Section(KWin32SectionName_Symbian) == 0) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Not EPOC Module")); sl@0: continue; // not an epoc DLL sl@0: } sl@0: sl@0: r=GatherDependencies(imp_etm.iModule); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: } sl@0: } sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::CompileDepLists")); sl@0: TInt result=KErrNone; sl@0: TInt c=iModules.Count(); sl@0: SModule* pM=(SModule*)&iModules[0]; sl@0: SModule* pE=pM+c; sl@0: for (; pMiDepList=(TInt*)Kern::Alloc(c*sizeof(TInt)); sl@0: if (!pM->iDepList) sl@0: return KErrNoMemory; sl@0: memset(pM->iDepList, 0xff, c*sizeof(TInt)); sl@0: Emulator::TModule etm((HINSTANCE)pM->iModuleHandle); sl@0: const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports(); sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Module %08x, imports=%08x flags=%08x", pM->iModuleHandle, imports, pM->iFlags)); sl@0: if (!imports || (pM->iFlags&EFlagAlwaysLoaded)) sl@0: continue; sl@0: sl@0: const SCapabilitySet& cap = pM->iS.iCaps; sl@0: const SCapabilitySet& disabledCaps=*(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities; sl@0: sl@0: TInt* pI=pM->iDepList; sl@0: for (; imports->Characteristics; ++imports ) sl@0: { sl@0: Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name)); sl@0: sl@0: if (!imp_etm.IsValid()) sl@0: continue; // spurious import sl@0: sl@0: if (imp_etm.Section(KWin32SectionName_Symbian) == 0) sl@0: continue; // not an epoc DLL sl@0: sl@0: TInt ix=Find((TInt)imp_etm.iModule); sl@0: __ASSERT_ALWAYS(ix>=0, MM::Panic(MM::ECompileDepLists)); sl@0: *pI++=ix; sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Depends on %08x, ix=%d", imp_etm.iModule, ix)); sl@0: sl@0: const SModule& dep = iModules[ix]; sl@0: sl@0: SCapabilitySet missingCaps; sl@0: SCapabilitySet depCaps = dep.iS.iCaps; sl@0: TUint32 checkFail = 0; sl@0: for (TInt i=0; i(pM->iModuleHandle),(LPWSTR)mainBuf); sl@0: TruncToNarrow(mainBuf8, mainBuf, mainlen); sl@0: } sl@0: TPtrC mainp(mainBuf8,mainlen); sl@0: TInt ix=mainp.LocateReverse('\\'); sl@0: if (ix>=0) sl@0: mainp.Set(mainp.Mid(ix+1)); sl@0: if (mainp.Length() && mainp[mainp.Length()-1]==')' && (ix=mainp.LocateReverse('('))>=0) sl@0: mainp.Set(mainp.Left(ix)); sl@0: sl@0: TUint8 depBuf8[MAX_PATH]; sl@0: TInt deplen; sl@0: { sl@0: TUint16 depBuf[MAX_PATH]; sl@0: deplen=Emulator::GetModuleFileName(reinterpret_cast(dep.iModuleHandle),(LPWSTR)depBuf); sl@0: TruncToNarrow(depBuf8, depBuf, deplen); sl@0: } sl@0: TPtrC depp(depBuf8,deplen); sl@0: if ((ix=depp.LocateReverse('\\'))>=0) sl@0: depp.Set(depp.Mid(ix+1)); sl@0: #ifndef __REMOVE_PLATSEC_DIAGNOSTICS__ sl@0: TInt r = PlatSec::LoaderCapabilityViolation(mainp, depp, missingCaps); sl@0: #else //__REMOVE_PLATSEC_DIAGNOSTICS__ sl@0: TInt r = PlatSec::EmitDiagnostic(); sl@0: #endif // !__REMOVE_PLATSEC_DIAGNOSTICS__ sl@0: if(r!=KErrNone) sl@0: result=r; sl@0: } sl@0: } sl@0: } sl@0: return result; sl@0: } sl@0: sl@0: #ifdef __VC32__ sl@0: #pragma warning( default : 4701 ) // enable warning C4701: local variable 'missingCaps' may be used without having been initialized sl@0: #endif sl@0: sl@0: void DModuleList::SetFlags() sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::SetFlags")); sl@0: TInt c=iModules.Count(); sl@0: SModule* pM=(SModule*)&iModules[0]; sl@0: SModule* pE=pM+c; sl@0: for (; pMiFlags &= ~EFlagMark; sl@0: TUint32 flags=Flags(pM); sl@0: if (flags & EFlagData) sl@0: pM->iFlags|=EFlagDataPresent; sl@0: if (flags & EFlagExe) sl@0: pM->iFlags|=EFlagExeInTree; sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Module %08x Flags=%08x", pM->iModuleHandle, pM->iFlags)); sl@0: } sl@0: pM=(SModule*)&iModules[0]; sl@0: for (; pMiDepList; sl@0: const TInt* pIE=pI+c; sl@0: while (pIiDepCount=dc; sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Module %08x DepCount=%d", pM->iModuleHandle, pM->iDepCount)); sl@0: } sl@0: } sl@0: sl@0: TUint32 DModuleList::Flags(SModule* aM) sl@0: { sl@0: TUint32 flags=aM->iFlags; sl@0: __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::Flags %08x", aM->iModuleHandle)); sl@0: if ((aM->iFlags & EFlagMark)==0) sl@0: { sl@0: aM->iFlags |= EFlagMark; sl@0: const TInt* pI=aM->iDepList; sl@0: const TInt* pE=pI+iModules.Count(); sl@0: while (pIiModuleHandle, flags)); sl@0: return flags; sl@0: } sl@0: sl@0: TInt DModuleList::LoadDependencies() sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LoadDependencies")); sl@0: TInt c=iModules.Count(); sl@0: SModule* pM=(SModule*)&iModules[0]; sl@0: SModule* pE=pM+c; sl@0: for (; pMiFlags; sl@0: __KTRACE_OPT(KDLL, Kern::Printf("ModuleHandle %08x flags %08x", pM->iModuleHandle, flags)); sl@0: if (!(flags & (EFlagDataPresent|EFlagExeInTree)) || (flags&EFlagAlwaysLoaded)) sl@0: continue; sl@0: SWin32Module w32m; sl@0: w32m.iWin32ModuleHandle=(TLinAddr)pM->iModuleHandle; sl@0: w32m.iCodeSeg=NULL; sl@0: TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m); sl@0: __KTRACE_OPT(KDLL, Kern::Printf("GlobalIndex=%d", ix)); sl@0: if (ix<0 && (flags & EFlagExe)) sl@0: return KErrNotSupported; // we never implicitly load an EXE sl@0: if (ix>=0) sl@0: { sl@0: pS=MM::Win32Modules[ix].iCodeSeg; sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Already loaded; CSEG=%08x %C", pS, pS)); sl@0: if (pS==iMain) sl@0: { sl@0: pS->iDepCount=pM->iDepCount; sl@0: if (pS->iDepCount) sl@0: { sl@0: pS->iDeps=(DCodeSeg**)Kern::AllocZ(pS->iDepCount*sizeof(DCodeSeg*)); sl@0: if (!pS->iDeps) sl@0: return KErrNoMemory; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (!(pS->iMark & DCodeSeg::EMarkLdr)) sl@0: { sl@0: pS->iMark |= DCodeSeg::EMarkLdr; sl@0: pS->CheckedOpen(); sl@0: } sl@0: pM->iFlags|=EFlagAlreadyLoaded; sl@0: } sl@0: pM->iCodeSeg=pS; sl@0: continue; sl@0: } sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Create new, depcount=%d", pM->iDepCount)); sl@0: pS=new DWin32CodeSeg; sl@0: if (!pS) sl@0: return KErrNoMemory; sl@0: TInt r=pS->CreateAlreadyLoaded((HMODULE)pM->iModuleHandle, pM->iDepCount); sl@0: if (r!=KErrNone) sl@0: { sl@0: delete pS; sl@0: return r; sl@0: } sl@0: pM->iCodeSeg=pS; sl@0: pS->iS = pM->iS; sl@0: pS->iModuleVersion = pM->iModuleVersion; sl@0: if (iMain->iAttr & ECodeSegAttKernel) sl@0: pS->iAttr |= ECodeSegAttKernel; sl@0: if (flags & EFlagData) sl@0: { sl@0: pS->iMark |= DCodeSeg::EMarkData|DCodeSeg::EMarkDataPresent; sl@0: if (!(flags&EFlagExe)) sl@0: pS->iMark |= DCodeSeg::EMarkDataInit; sl@0: } sl@0: if ( (flags & EFlagData) || ((flags&(EFlagExe|EFlagExeInTree))==EFlagExeInTree) ) sl@0: { sl@0: if (iAttachProcess) sl@0: { sl@0: pS->iExeCodeSeg = iAttachProcess->CodeSeg(); sl@0: pS->SetAttachProcess(iAttachProcess); sl@0: } sl@0: } sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: void DModuleList::LinkDependencies() sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LinkDependencies")); sl@0: TInt c=iModules.Count(); sl@0: SModule* pM=(SModule*)&iModules[0]; sl@0: SModule* pE=pM+c; sl@0: for (; pMiCodeSeg; sl@0: if (!pS || (pM->iFlags&EFlagAlreadyLoaded)) sl@0: continue; sl@0: const TInt* pI=pM->iDepList; sl@0: const TInt* pIE=pI+c; sl@0: while (pIiDeps[pS->iNextDep++]=pD; sl@0: } sl@0: } sl@0: pM=(SModule*)&iModules[0]; sl@0: } sl@0: sl@0: TInt DModuleList::Loaded() sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::Loaded()")); sl@0: TInt c=iModules.Count(); sl@0: SModule* pM=(SModule*)&iModules[0]; sl@0: SModule* pE=pM+c; sl@0: TInt r=KErrNone; sl@0: for (; pMiCodeSeg; sl@0: if (pS && pS!=iMain) sl@0: { sl@0: pS->FinaliseRecursiveFlags(); sl@0: pS->iMark |= DCodeSeg::EMarkLoaded; sl@0: } sl@0: } sl@0: if (r==KErrNone) sl@0: { sl@0: pM=(SModule*)&iModules[0]; sl@0: for (; pMiCodeSeg=NULL; // cleanup will occur by EMarkLdr if needed sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt MakeDll(HANDLE aFile) sl@0: { sl@0: IMAGE_DOS_HEADER dosh; sl@0: DWORD bytes; sl@0: ReadFile(aFile, &dosh, sizeof(dosh), &bytes, NULL); sl@0: if ( IMAGE_DOS_SIGNATURE != dosh.e_magic ) sl@0: return KErrArgument; sl@0: if (dosh.e_lfarlc < sizeof(dosh)) sl@0: return KErrArgument; sl@0: SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN); sl@0: IMAGE_NT_HEADERS32 peh; sl@0: ReadFile(aFile, &peh, sizeof(peh), &bytes, NULL); sl@0: if ( peh.Signature != IMAGE_NT_SIGNATURE ) sl@0: return KErrArgument; sl@0: sl@0: peh.FileHeader.Characteristics |= IMAGE_FILE_DLL; sl@0: peh.OptionalHeader.AddressOfEntryPoint = 0; sl@0: SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN); sl@0: WriteFile(aFile, &peh, sizeof(peh), &bytes, NULL); sl@0: return KErrNone; sl@0: } sl@0: sl@0: wchar_t* TempModuleName(const wchar_t* aExe) sl@0: { sl@0: static TInt ModuleGeneration = 0; sl@0: static TInt Time = 0; sl@0: sl@0: WCHAR ex_[KMaxFileName + 1]; sl@0: sl@0: if (!Time) sl@0: { sl@0: SYSTEMTIME st; sl@0: GetSystemTime(&st); sl@0: Time = st.wSecond + st.wMinute*60 + st.wHour*3600; sl@0: } sl@0: sl@0: const char* imagePath = Property::GetString("EmulatorImagePath"); sl@0: WCHAR* p = ex_; sl@0: while ((*p++ = *imagePath++) != 0) sl@0: ; sl@0: wcscpy(p-1, wcsrchr(aExe, '\\') + 1); sl@0: p = ex_ + wcslen(ex_); sl@0: *p++ = '('; sl@0: _itow(Time, p, 36); sl@0: p += wcslen(p); sl@0: *p++ = '-'; sl@0: _itow(ModuleGeneration++, p, 10); sl@0: p += wcslen(p); sl@0: *p++ = ')'; sl@0: *p++ = '\0'; sl@0: wchar_t* file = (wchar_t*)Kern::Alloc((p-ex_)*sizeof(WCHAR)); sl@0: if (file) sl@0: wcscpy(file, ex_); sl@0: return file; sl@0: } sl@0: sl@0: DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&) sl@0: // sl@0: // Create a new instance of this class. sl@0: // sl@0: { sl@0: sl@0: __KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg")); sl@0: return new DWin32CodeSeg; sl@0: } sl@0: sl@0: DWin32CodeSeg::DWin32CodeSeg() sl@0: // sl@0: // Constructor sl@0: // sl@0: { sl@0: } sl@0: sl@0: DWin32CodeSeg::~DWin32CodeSeg() sl@0: // sl@0: // Destructor sl@0: // sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Destruct %C", this)); sl@0: DBase::Delete(iModuleList); sl@0: if (iWinInstance) sl@0: { sl@0: DCodeSeg::Wait(); sl@0: SWin32Module w32m; sl@0: w32m.iWin32ModuleHandle=(TLinAddr)iModuleHandle; sl@0: w32m.iCodeSeg=NULL; sl@0: TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m); sl@0: if (ix>=0) sl@0: { sl@0: if (iAlwaysLoaded) sl@0: MM::Win32Modules[ix].iCodeSeg=NULL; sl@0: else sl@0: MM::Win32Modules.Remove(ix); sl@0: } sl@0: // Kernel process has to be told to unmap code seg to work round sl@0: // a problem where failed driver code seg is not unmapped before delete sl@0: K::TheKernelProcess->UnmapCodeSeg(this); sl@0: Emulator::FreeLibrary(iWinInstance); sl@0: DCodeSeg::Signal(); sl@0: } sl@0: if (iModuleFile) sl@0: { sl@0: Emulator::DeleteFile(iModuleFile); sl@0: Kern::Free(iModuleFile); sl@0: } sl@0: Kern::Free(iDataCopy); sl@0: DCodeSeg::Destruct(); sl@0: } sl@0: sl@0: TInt DWin32CodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess) sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::DoCreate %C proc %O", this, aProcess)); sl@0: sl@0: TBool exe=(iExeCodeSeg==this); sl@0: if (exe && (iAttr&ECodeSegAttKernel)) sl@0: { sl@0: // loading EKERN.EXE sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN")); sl@0: TUint16 fileNameW[KMaxFileName]; sl@0: ExpandToWide(fileNameW, iFileName->Ptr(), iFileName->Length()); sl@0: fileNameW[iFileName->Length()] = '\0'; sl@0: iWinInstance = Emulator::LoadLibrary((LPCWSTR)fileNameW); sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN %08x", iWinInstance)); sl@0: if (!iWinInstance) sl@0: return KErrGeneral; sl@0: if (aInfo.iTotalDataSize) sl@0: iMark|=EMarkData|EMarkDataPresent; sl@0: KernelCodeSeg=this; sl@0: KernelModuleHandle=Emulator::GetModuleHandle((LPCWSTR)fileNameW); sl@0: return RegisterCodeSeg(KernelModuleHandle); sl@0: } sl@0: TWin32Filename w32fn(*iFileName); sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : w32fn=%S",iFileName)) sl@0: DWin32Process* p=(DWin32Process*)aProcess; sl@0: TInt r=KErrNone; sl@0: DCodeSeg::Wait(); sl@0: HMODULE h = Emulator::GetModuleHandle(w32fn); sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : h=%08x exe=%08x",h,exe)); sl@0: if (h && exe) sl@0: { sl@0: if (h == GetModuleHandleA(NULL)) sl@0: { sl@0: // This was the executable that was used to run the emulator sl@0: // so all relocations will be valid and we can use it sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : initial exe")); sl@0: if (BootComplete) sl@0: goto makecopy; // we can only do this once however sl@0: iWinInstance = Emulator::LoadLibrary(w32fn); sl@0: BootComplete = ETrue; sl@0: } sl@0: else sl@0: r=KErrAlreadyExists; // can't load same EXEXP twice sl@0: } sl@0: else if (h) sl@0: { sl@0: // Already loaded DLL sl@0: // Code segment doesn't exist so create it sl@0: __KTRACE_OPT(KDLL,Kern::Printf("Already loaded, module %08x",h)); sl@0: iWinInstance = Emulator::LoadLibrary(w32fn); sl@0: } sl@0: else if (iAttr & ECodeSegAttHDll) sl@0: { sl@0: // EXE with exports (EXEXP target) - can only have one instance sl@0: // or DLL not already loaded sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EXEXP or new DLL")); sl@0: iWinInstance = Emulator::LoadLibrary(w32fn); sl@0: if (iWinInstance) sl@0: h=Emulator::GetModuleHandle(w32fn); sl@0: } sl@0: else sl@0: { sl@0: // EXE with no exports. In order that multiple instances of the EXE may be run, sl@0: // we make a copy of the EXE file to a name which is unique across instances, sl@0: // set the DLL flag and load it as a DLL. sl@0: makecopy: sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : MakeCopy")); sl@0: h=0; sl@0: iModuleFile = TempModuleName(w32fn); sl@0: if (!iModuleFile) sl@0: r=KErrNoMemory; sl@0: else if (Emulator::CopyFile(w32fn,iModuleFile,FALSE)) sl@0: { sl@0: DWORD fattr = Emulator::GetFileAttributes(iModuleFile); sl@0: if (fattr != 0xffffffff && Emulator::SetFileAttributes(iModuleFile, fattr & ~FILE_ATTRIBUTE_READONLY)) sl@0: { sl@0: HANDLE f = Emulator::CreateFile(iModuleFile,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL); sl@0: if (INVALID_HANDLE_VALUE != f) sl@0: { sl@0: r = MakeDll(f); sl@0: CloseHandle(f); sl@0: if (r==KErrNone) sl@0: { sl@0: iWinInstance = Emulator::LoadLibrary(iModuleFile); sl@0: if (iWinInstance) sl@0: h=Emulator::GetModuleHandle(iModuleFile); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: } sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d iWinInstance=%08x",__LINE__,r,iWinInstance)); sl@0: if (r==KErrNone && !iWinInstance) sl@0: r=Emulator::LastError(); sl@0: __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d",__LINE__,r)); sl@0: if (r==KErrNone) sl@0: { sl@0: const char* entry_name = exe ? "_E32Startup" : "_E32Dll" ; sl@0: aInfo.iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, entry_name); sl@0: if (!aInfo.iFileEntryPoint) sl@0: { sl@0: r=KErrNotSupported; sl@0: } sl@0: else sl@0: { sl@0: r=RegisterCodeSeg(h); sl@0: } sl@0: sl@0: if (r == KErrNone) sl@0: { sl@0: r = CopyDataBss(); sl@0: } sl@0: } sl@0: if (r==KErrNone && aInfo.iTotalDataSize && !iAlwaysLoaded) sl@0: { sl@0: iMark|=EMarkData|EMarkDataPresent; sl@0: if (!exe) sl@0: iMark|=EMarkDataInit; sl@0: } sl@0: sl@0: if (r==KErrNone) sl@0: r=ProcessImports(p); sl@0: __KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this)); sl@0: DCodeSeg::Signal(); sl@0: return r; sl@0: } sl@0: sl@0: TInt DWin32CodeSeg::RegisterCodeSeg(HMODULE aModule) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %C RegisterCodeSeg(%08x)", this, aModule)); sl@0: Emulator::TModule etm(aModule); sl@0: const IMAGE_NT_HEADERS32* nth=etm.NtHeader(); sl@0: iRunAddress = (TLinAddr)aModule; sl@0: iSize = nth->OptionalHeader.SizeOfImage; sl@0: SWin32Module w32m; sl@0: w32m.iWin32ModuleHandle=(TLinAddr)aModule; sl@0: w32m.iCodeSeg=this; sl@0: TInt r=KErrNone; sl@0: TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m); sl@0: if (ix>=0) sl@0: { sl@0: SWin32Module& wmr=MM::Win32Modules[ix]; sl@0: __ASSERT_ALWAYS(!wmr.iCodeSeg, MM::Panic(MM::EInvalidSharedModule)); sl@0: wmr.iCodeSeg=this; sl@0: iAlwaysLoaded=ETrue; sl@0: } sl@0: else sl@0: r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m); sl@0: if (r==KErrNone) sl@0: { sl@0: iModuleHandle=aModule; sl@0: iCodeSegId=++MM::NextCodeSegId; sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DWin32CodeSeg::CreateAlreadyLoaded(HMODULE aModule, TInt aDepCount) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %08x CreateAlreadyLoaded(%08x,%d)", this, aModule, aDepCount)); sl@0: Emulator::TModule etm(aModule); sl@0: etm.GetUids(iUids); sl@0: TInt32 uid1=iUids.iUid[0].iUid; sl@0: if (uid1!=KDynamicLibraryUidValue) // only implicitly load DLLs sl@0: return KErrNotSupported; sl@0: sl@0: WCHAR name[MAX_PATH+1]; sl@0: TInt r=Emulator::GetModuleFileName(aModule, name); sl@0: if (!r) sl@0: return Emulator::LastError(); sl@0: TUint8 name8[MAX_PATH+1]; sl@0: TruncToNarrow(name8,(const TUint16*)name,-1); sl@0: sl@0: //SL: sl@0: __KTRACE_OPT(KDLL, Kern::Printf("Loading library %s", name8)); sl@0: sl@0: TPtrC fpptr((const TText*)name8); sl@0: TInt slash=fpptr.LocateReverse('\\'); sl@0: TPtrC nptr=fpptr.Mid(slash+1); sl@0: iFileName=HBuf::New(nptr); sl@0: if (!iFileName) sl@0: return KErrNoMemory; sl@0: iRootName.Set(*iFileName); sl@0: iExtOffset = iFileName->LocateReverse('.'); sl@0: if (iExtOffset==KErrNotFound) sl@0: iExtOffset = iFileName->Length(); sl@0: iModuleVersion = 0x00010000u; sl@0: iDepCount=aDepCount; sl@0: if (iDepCount) sl@0: { sl@0: iDeps=(DCodeSeg**)Kern::AllocZ(iDepCount*sizeof(DCodeSeg*)); sl@0: if (!iDeps) sl@0: return KErrNoMemory; sl@0: } sl@0: iWinInstance = Emulator::LoadLibrary(name); sl@0: if (!iWinInstance) sl@0: return Emulator::LastError(); sl@0: iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, "_E32Dll"); sl@0: if (!iFileEntryPoint) sl@0: return KErrNotSupported; sl@0: iEntryPtVeneer = iFileEntryPoint; sl@0: r=RegisterCodeSeg(aModule); sl@0: if (r == KErrNone) sl@0: r = CopyDataBss(); sl@0: if (r == KErrNone) sl@0: r = CodeSegsByName.InsertInOrderAllowRepeats(this, &CompareCodeSegsByName); sl@0: if (r == KErrNone) sl@0: r = CodeSegsByAddress.Add(this); sl@0: if (r==KErrNone) sl@0: { sl@0: GlobalList.Add(&iLink); sl@0: iAsyncDeleteNext=this; sl@0: } sl@0: __KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this)); sl@0: return r; sl@0: } sl@0: sl@0: TInt DWin32CodeSeg::CopyDataBss() sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::CopyDataBss()")); sl@0: sl@0: Emulator::TModule etm(iModuleHandle); sl@0: const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian); sl@0: if (!(hdr->iFlags & KEmulatorImageFlagAllowDllData)) sl@0: return KErrNone; sl@0: const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData); sl@0: const IMAGE_SECTION_HEADER* bss=etm.SectionHeader(KWin32SectionName_EpocBss); sl@0: if (data) sl@0: { sl@0: iRealDataSize = data->Misc.VirtualSize; sl@0: iDataDest = (TLinAddr)etm.Translate(data->VirtualAddress); sl@0: iDataCopy = Kern::Alloc(iRealDataSize); sl@0: if (!iDataCopy) sl@0: return KErrNoMemory; sl@0: memcpy(iDataCopy, (const TAny*)iDataDest, iRealDataSize); sl@0: } sl@0: if (bss) sl@0: { sl@0: iRealBssSize = bss->Misc.VirtualSize; sl@0: iBssDest = (TLinAddr)etm.Translate(bss->VirtualAddress); sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt DWin32CodeSeg::ProcessImports(DProcess* aProcess) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::ProcessImports(%O)", aProcess)); sl@0: iModuleList=new DModuleList(this, aProcess); sl@0: if (!iModuleList) sl@0: return KErrNoMemory; sl@0: TInt r=iModuleList->GatherDependencies(iModuleHandle); sl@0: if (r!=KErrNone) sl@0: return r; sl@0: TInt ix=iModuleList->Find((TInt)iModuleHandle); sl@0: DModuleList::SModule& mm=iModuleList->iModules[ix]; sl@0: r=iModuleList->CompileDepLists(); sl@0: if (r==KErrNone) sl@0: { sl@0: iModuleList->SetFlags(); sl@0: r=iModuleList->LoadDependencies(); sl@0: if (r==KErrNone) sl@0: { sl@0: if ((mm.iFlags&(DModuleList::EFlagDataPresent|DModuleList::EFlagExeInTree)) && !(mm.iFlags&DModuleList::EFlagAlwaysLoaded)) sl@0: { sl@0: if (aProcess) sl@0: { sl@0: iExeCodeSeg=aProcess->CodeSeg(); sl@0: SetAttachProcess(aProcess); sl@0: } sl@0: } sl@0: iModuleList->LinkDependencies(); sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DWin32CodeSeg::Loaded(TCodeSegCreateInfo& aInfo) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded()")); sl@0: TInt r=KErrNone; sl@0: if (iModuleList) sl@0: { sl@0: r=iModuleList->Loaded(); sl@0: if (r==KErrNone) sl@0: { sl@0: DBase::Delete(iModuleList); sl@0: iModuleList=NULL; sl@0: } sl@0: } sl@0: if (r==KErrNone) sl@0: r=DCodeSeg::Loaded(aInfo); sl@0: __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded() - %d", r)); sl@0: return r; sl@0: } sl@0: sl@0: void DWin32CodeSeg::ReadExportDir(TUint32*) sl@0: { sl@0: // not needed sl@0: } sl@0: sl@0: TBool DWin32CodeSeg::FindCheck(DProcess* /*aProcess*/) sl@0: { sl@0: // We never create multiple copies of the same code segment, sl@0: // so if code segment exists, allow it to be found. sl@0: // CodeSegOpen will fail if it is incompatible. sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool DWin32CodeSeg::OpenCheck(DProcess* aProcess) sl@0: { sl@0: __KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess)); sl@0: if (!aProcess) sl@0: return EFalse; // never reuse EXE code segments sl@0: return ETrue; sl@0: } sl@0: sl@0: TLibraryFunction DWin32CodeSeg::Lookup(TInt aOrdinal) sl@0: // sl@0: // Find an exported function by ordinal sl@0: // sl@0: { sl@0: TLibraryFunction f = NULL; sl@0: if (aOrdinal != 0) sl@0: { sl@0: sl@0: f = (TLibraryFunction)Emulator::GetProcAddress(iWinInstance, (const char *)aOrdinal); sl@0: if ((TLinAddr)f == iFileEntryPoint) sl@0: f = NULL; sl@0: } sl@0: else sl@0: { sl@0: // Find 0th Ordinal, which should be named symbol export data, from named data segment sl@0: Emulator::TModule etm(iModuleHandle); sl@0: f = (TLibraryFunction)etm.Section(KWin32SectionName_NmdExpData); sl@0: } sl@0: __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Lookup(%d)->%08x",aOrdinal,f)); sl@0: return f; sl@0: } sl@0: sl@0: DCodeSeg* DCodeSeg::FindRomCode(const TAny*) sl@0: { sl@0: // never used sl@0: return NULL; sl@0: } sl@0: sl@0: void DWin32CodeSeg::InitData() sl@0: { sl@0: } sl@0: sl@0: TInt DWin32CodeSeg::GetMemoryInfo(TModuleMemoryInfo&, DProcess*) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: void DWin32CodeSeg::Info(TCodeSegCreateInfo& aInfo) sl@0: { sl@0: Emulator::TModule etm(iModuleHandle); sl@0: const IMAGE_NT_HEADERS32* nth=etm.NtHeader(); sl@0: const IMAGE_EXPORT_DIRECTORY* exd= sl@0: (const IMAGE_EXPORT_DIRECTORY*)etm.Translate(nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress); sl@0: const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian); sl@0: TBool isExe = hdr && hdr->iUids[0].iUid==KExecutableImageUidValue; sl@0: const IMAGE_SECTION_HEADER* text=etm.SectionHeader(KWin32SectionName_Text); sl@0: const IMAGE_SECTION_HEADER* rdata=etm.SectionHeader(KWin32SectionName_RData); sl@0: const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData); sl@0: if (!isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData)) sl@0: data = NULL; sl@0: aInfo.iTextSize=text->Misc.VirtualSize; sl@0: aInfo.iCodeSize=text->Misc.VirtualSize; sl@0: if (rdata) sl@0: aInfo.iCodeSize+=rdata->Misc.VirtualSize; sl@0: aInfo.iDataSize=data ? (data->SizeOfRawData) : 0; sl@0: aInfo.iBssSize=data ? (data->Misc.VirtualSize-data->SizeOfRawData) : 0; sl@0: aInfo.iTotalDataSize=aInfo.iDataSize+aInfo.iBssSize; sl@0: aInfo.iExportDir=(TLinAddr)exd; sl@0: aInfo.iExportDirCount=exd ? exd->NumberOfFunctions : 0; sl@0: aInfo.iCodeLoadAddress=(TLinAddr)etm.Translate(text->VirtualAddress); sl@0: aInfo.iCodeRunAddress=aInfo.iCodeLoadAddress; sl@0: aInfo.iDataLoadAddress=data ? (TLinAddr)etm.Translate(data->VirtualAddress) : 0; sl@0: aInfo.iDataRunAddress=aInfo.iDataLoadAddress; sl@0: DCodeSeg::Info(aInfo); sl@0: } sl@0: sl@0: TLinAddr DCodeSeg::ExceptionDescriptor() sl@0: { sl@0: return 0; // not used on emulator sl@0: } sl@0: sl@0: TInt MM::RegisterModule(HMODULE aModule) sl@0: { sl@0: __KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule %08x",aModule)); sl@0: SWin32Module w32m; sl@0: w32m.iWin32ModuleHandle=(TLinAddr)aModule; sl@0: w32m.iCodeSeg=NULL; sl@0: TInt r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m); sl@0: __KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule ret %d",r)); sl@0: return r; sl@0: } sl@0: sl@0: _LIT(KRomSysBin, "Z:\\sys\\bin"); sl@0: sl@0: // Massage file names returned for stuff in EPOCROOT\epoc32\release\wins\xxxx\ sl@0: // in order to make them appear to be in z:\system\libs sl@0: void P::NormalizeExecutableFileName(TDes& a) sl@0: { sl@0: __KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName %lS", &a)); sl@0: if (a.Length()<3 || a[1]!=':' || a[2]!='\\') sl@0: { sl@0: // don't have a drive so assume in 'ROM' sl@0: TFileName initial(a); sl@0: a=KRomSysBin(); sl@0: if (initial.Length()==0 || initial[0]!='\\') sl@0: a.Append('\\'); sl@0: a+=initial; sl@0: __KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName -> %lS", &a)); sl@0: } sl@0: } sl@0: sl@0: TInt LookupDllUid(TInt aModule) sl@0: { sl@0: TInt r = KDllUid_Default; sl@0: Kern::AccessCode(); sl@0: SWin32Module w32m; sl@0: w32m.iWin32ModuleHandle=(TLinAddr)aModule; sl@0: TInt ix; sl@0: MM::Win32Modules.SpecificFindInUnsignedKeyOrder(w32m, ix, EArrayFindMode_Last); sl@0: if (ix>0) sl@0: { sl@0: DWin32CodeSeg* pS = MM::Win32Modules[ix-1].iCodeSeg; sl@0: if (pS && pS->iFileEntryPoint==(TLinAddr)aModule) sl@0: r = pS->iCodeSegId; sl@0: } sl@0: Kern::EndAccessCode(); sl@0: return r; sl@0: } sl@0: sl@0: