Update contrib.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\memmodel\emul\win32\mcodeseg.cpp
18 #define __INCLUDE_ALL_SUPPORTED_CAPABILITIES__
24 #define __CHECKHEAP() ((RHeapK*)K::Allocator)->Check()
26 static TBool BootComplete; // flag set when boot EXE is loaded as an EPOC process
27 static DWin32CodeSeg* KernelCodeSeg;
28 static HMODULE KernelModuleHandle;
30 GLREF_C TInt CompareCodeSegsByName(const DCodeSeg& aA, const DCodeSeg& aB);
32 void TruncToNarrow(TUint8* aDes, const TUint16* aSrc, int aLen)
34 //converts to narrow by dumping the high order byte
39 for(int index=0;*aSrc;index++)
40 *aDes++ = (TUint8)*aSrc++;
44 for(int index=0;index<aLen;index++)
45 *aDes++ = (TUint8)*aSrc++;
49 void ExpandToWide(TUint16* aDes, const TUint8* aSrc, int aLen)
53 for(int index=0;index<aLen;index++)
54 *aDes++ = (TUint16)*aSrc++;
59 void DumpWin32CodeSeg(DWin32CodeSeg& a)
61 const TUint32* uid=(const TUint32*)&a.iUids;
62 Kern::Printf("DWin32CodeSeg@%08x:",&a);
63 Kern::Printf("iLink = %08x %08x", a.iLink.iNext, a.iLink.iPrev);
64 Kern::Printf("iTempLink = %08x %08x", a.iTempLink.iNext, a.iTempLink.iPrev);
65 Kern::Printf("iGbgLink = %08x %08x", a.iGbgLink.iNext, a.iGbgLink.iPrev);
66 Kern::Printf("iAccessCount = %d", a.iAccessCount);
67 Kern::Printf("iEntryPtVeneer = %08x", a.iEntryPtVeneer);
68 Kern::Printf("iFileEntryPoint = %08x", a.iFileEntryPoint);
69 Kern::Printf("iFileName = %lS", a.iFileName);
70 Kern::Printf("iRootName = %lS", &a.iRootName);
71 Kern::Printf("iExtOffset = %d", a.iExtOffset);
72 Kern::Printf("iModuleVersion = %08x", a.iModuleVersion);
73 Kern::Printf("iUids = %08x %08x %08x", uid[0], uid[1], uid[2]);
74 Kern::Printf("iDepCount=%d iDeps=%08x", a.iDepCount, a.iDeps);
75 Kern::Printf("iNextDep=%d, iMark=%08x, iAttr=%08x", a.iNextDep, a.iMark, a.iAttr);
76 Kern::Printf("iExeCodeSeg=%08x, iAttachProcess=%O", a.iExeCodeSeg, a.iAttachProcess);
77 Kern::Printf("iWinInstance = %08x", a.iWinInstance);
78 Kern::Printf("iModuleHandle = %08x", a.iModuleHandle);
79 Kern::Printf("iModuleFile = %08x", a.iModuleFile);
80 Kern::Printf("iAlwaysLoaded = %08x", a.iAlwaysLoaded);
81 Kern::Printf("iModuleList = %08x", a.iModuleList);
85 void ExecInEntryPoint()
87 // This function will be called if an Exec:: call is attempted in the entry
88 // point of a DLL which didn't specify 'epocallowdlldata'
89 Kern::Fault("BAD DLL STATIC",0);
92 static const SFastExecTable DummyFastExecTable={0,{0}};
93 static const SSlowExecTable DummySlowExecTable={0,(TLinAddr)ExecInEntryPoint,0,{{0,0}}};
95 // Force a call to a DLL entry point to initialise any gratuitous writeable data
96 // generated by the compiler.
97 // Change exec table to prevent any executive calls in case someone forgot to
98 // use the 'epocallowdlldata' option.
99 void ForceEntryPointCall(TLinAddr aEntryPoint)
101 __KTRACE_OPT(KDLL,Kern::Printf("ForceEntryPoint %08x", aEntryPoint));
103 NThread* nthrd = NKern::CurrentThread();
104 const SFastExecTable* fast = nthrd->iFastExecTable;
105 const SSlowExecEntry* slow = nthrd->iSlowExecTable;
106 nthrd->iFastExecTable = (SFastExecTable*)&DummyFastExecTable;
107 nthrd->iSlowExecTable = DummySlowExecTable.iEntries;
108 TLibraryEntry ep = (TLibraryEntry)aEntryPoint;
109 (*ep)(KModuleEntryReasonProcessAttach);
110 nthrd->iFastExecTable = fast;
111 nthrd->iSlowExecTable = slow;
118 inline TWin32Filename()
120 inline TWin32Filename(const TDesC& aFilename)
122 inline TWin32Filename& operator=(const TDesC& aFilename)
123 {Set(aFilename);return *this;}
124 inline operator LPCWSTR() const
127 void Set(const TDesC& aFilename);
129 WCHAR iBuf[KMaxFileName + 1];
132 void TWin32Filename::Set(const TDesC& aFilename)
134 TUint16 fileName[KMaxFileName];
135 ExpandToWide(fileName, aFilename.Ptr(), aFilename.Length());
136 TPtr p((TUint8*)iBuf,KMaxFileName<<1);
137 Property::MapFilename(p, TPtrC((TUint8*)fileName,aFilename.Length()<<1));
138 iBuf[p.Length()>>1] = '\0';
141 class DModuleList : public DBase
147 EFlagDataPresent=0x02,
148 EFlagAlreadyLoaded=0x04,
151 EFlagAlwaysLoaded=0x20,
157 TLinAddr iModuleHandle;
158 DWin32CodeSeg* iCodeSeg;
161 TUint32 iModuleVersion;
166 DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess);
167 virtual ~DModuleList();
168 TInt Find(TInt aModule);
169 TInt GatherDependencies(HMODULE aModule);
170 TInt CompileDepLists();
172 TUint32 Flags(SModule* aM);
173 TInt LoadDependencies();
174 void LinkDependencies();
177 DWin32CodeSeg* iMain;
178 DProcess* iAttachProcess;
179 RArray<SModule> iModules;
182 DModuleList::DModuleList(DWin32CodeSeg* aMainSeg, DProcess* aProcess)
183 : iMain(aMainSeg), iAttachProcess(aProcess),
184 iModules(8, _FOFF(SModule,iModuleHandle), 2*256)
188 DModuleList::~DModuleList()
190 TInt c = iModules.Count();
193 SModule* pM = (SModule*)&iModules[0];
194 SModule* pE = pM + c;
197 Kern::Free(pM->iDepList);
203 TInt DModuleList::Find(TInt aModule)
206 mod.iModuleHandle=(TLinAddr)aModule;
207 return iModules.FindInUnsignedKeyOrder(mod);
210 Populate iModules with SModule entries corresponding to supplied HModule and all of its dependencies,
213 @param aModule A Windows module handle
214 @return KErrNone if successful
216 TInt DModuleList::GatherDependencies(HMODULE aModule)
218 __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
219 Emulator::TModule etm(aModule);
221 mod.iModuleHandle=(TLinAddr)aModule;
226 TUidType& uidref=*(TUidType*)uid;
227 const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
229 return KErrNotSupported;
230 __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));
232 // Overide capabilities in image
233 const SCapabilitySet& disabledCaps = *(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
234 for(TInt i=0; i<SCapabilitySet::ENCapW; i++)
236 mod.iS.iCaps[i] |= disabledCaps[i];
237 mod.iS.iCaps[i] &= AllSupportedCapabilities[i];
239 mod.iModuleVersion = hdr->iModuleVersion;
240 mod.iFlags = (hdr->iFlags & KEmulatorImageFlagAllowDllData) ? EFlagData|EFlagDataPresent : 0;
241 uidref = *(const TUidType*)&hdr->iUids[0];
242 TBool isExe = (uid[0]==KExecutableImageUidValue);
243 TBool data_section_present = (etm.Section(KWin32SectionName_EpocData) != NULL);
244 if (data_section_present && isExe)
245 mod.iFlags = EFlagData|EFlagDataPresent;
246 __KTRACE_OPT(KDLL,Kern::Printf("DataSectionPresent = %x", data_section_present));
248 // Can't do this for CodeWarrior since it sticks everything in .data, even constants
249 // On VC6 this check works for Base code, but not for some other code.
250 // if (data_section_present && !isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
251 // return KErrNotSupported;
253 if (!data_section_present)
256 mod.iFlags |= EFlagExe|EFlagExeInTree;
259 w32m.iWin32ModuleHandle=(TLinAddr)aModule;
261 TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
262 __KTRACE_OPT(KDLL, Kern::Printf("GlobalIx=%d", ix));
263 if ((ix>=0 && !MM::Win32Modules[ix].iCodeSeg) || aModule==KernelModuleHandle)
264 mod.iFlags|=EFlagAlwaysLoaded;
265 TInt r=iModules.InsertInUnsignedKeyOrder(mod);
266 __KTRACE_OPT(KDLL, Kern::Printf("Flags=%08x, InsertRes=%d", mod.iFlags, r));
267 if (r==KErrAlreadyExists)
271 if (mod.iFlags & EFlagAlwaysLoaded)
272 return KErrNone; // stop if we reach an extension or variant
273 if (data_section_present && (mod.iFlags & EFlagData)==0)
275 // DLL, .data present but 'epocallowdlldata' not specified
276 // - either the compiler forgetting that something's constant or
277 // developer forgetting to specify 'epocallowdlldata'.
278 // call entry point from here to keep the compiler happy
279 const char* entry_name = "_E32Dll" ;
280 TLinAddr ep = (TLinAddr)Emulator::GetProcAddress(aModule, entry_name);
281 __NK_ASSERT_ALWAYS(ep!=0);
282 ForceEntryPointCall(ep);
285 const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
288 for (; imports->Characteristics; ++imports )
290 __KTRACE_OPT(KDLL, { TPtrC8 n((const TText8*)etm.Translate(imports->Name)); Kern::Printf("Importing from %S", &n);} );
291 Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
293 if (!imp_etm.IsValid())
295 __KTRACE_OPT(KDLL, Kern::Printf("Spurious import"));
299 if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
301 __KTRACE_OPT(KDLL, Kern::Printf("Not EPOC Module"));
302 continue; // not an epoc DLL
305 r=GatherDependencies(imp_etm.iModule);
310 __KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::GatherDependencies %08x %08x %C", aModule, iMain, iMain));
315 #pragma warning( disable : 4701 ) // disable warning C4701: local variable 'missingCaps' may be used without having been initialized
319 Iterate through imports (if any) of each SModule in list. Populate iDepList with the indicies (in iModules)
320 of directly required modules. Checks that dependencies are legal under platsec.
321 @return KErrNone on success.
323 TInt DModuleList::CompileDepLists()
325 __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::CompileDepLists"));
326 TInt result=KErrNone;
327 TInt c=iModules.Count();
328 SModule* pM=(SModule*)&iModules[0];
332 pM->iDepList=(TInt*)Kern::Alloc(c*sizeof(TInt));
335 memset(pM->iDepList, 0xff, c*sizeof(TInt));
336 Emulator::TModule etm((HINSTANCE)pM->iModuleHandle);
337 const IMAGE_IMPORT_DESCRIPTOR* imports = etm.Imports();
338 __KTRACE_OPT(KDLL, Kern::Printf("Module %08x, imports=%08x flags=%08x", pM->iModuleHandle, imports, pM->iFlags));
339 if (!imports || (pM->iFlags&EFlagAlwaysLoaded))
342 const SCapabilitySet& cap = pM->iS.iCaps;
343 const SCapabilitySet& disabledCaps=*(SCapabilitySet*)&TheSuperPage().iDisabledCapabilities;
345 TInt* pI=pM->iDepList;
346 for (; imports->Characteristics; ++imports )
348 Emulator::TModule imp_etm((PCSTR)etm.Translate(imports->Name));
350 if (!imp_etm.IsValid())
351 continue; // spurious import
353 if (imp_etm.Section(KWin32SectionName_Symbian) == 0)
354 continue; // not an epoc DLL
356 TInt ix=Find((TInt)imp_etm.iModule);
357 __ASSERT_ALWAYS(ix>=0, MM::Panic(MM::ECompileDepLists));
359 __KTRACE_OPT(KDLL, Kern::Printf("Depends on %08x, ix=%d", imp_etm.iModule, ix));
361 const SModule& dep = iModules[ix];
363 SCapabilitySet missingCaps;
364 SCapabilitySet depCaps = dep.iS.iCaps;
365 TUint32 checkFail = 0;
366 for (TInt i=0; i<SCapabilitySet::ENCapW; ++i)
368 depCaps[i] = dep.iS.iCaps[i]|disabledCaps[i];
369 TUint32 missing = cap[i] & ~depCaps[i];
370 missingCaps[i] = missing;
371 checkFail |= missing;
374 __KTRACE_OPT(KDLL, Kern::Printf("Cap=%08x %08x, DepCap=%08x %08x", cap[1], cap[0], depCaps[1], depCaps[0]));
378 TUint8 mainBuf8[MAX_PATH];
381 TUint16 mainBuf[MAX_PATH];
382 mainlen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(pM->iModuleHandle),(LPWSTR)mainBuf);
383 TruncToNarrow(mainBuf8, mainBuf, mainlen);
385 TPtrC mainp(mainBuf8,mainlen);
386 TInt ix=mainp.LocateReverse('\\');
388 mainp.Set(mainp.Mid(ix+1));
389 if (mainp.Length() && mainp[mainp.Length()-1]==')' && (ix=mainp.LocateReverse('('))>=0)
390 mainp.Set(mainp.Left(ix));
392 TUint8 depBuf8[MAX_PATH];
395 TUint16 depBuf[MAX_PATH];
396 deplen=Emulator::GetModuleFileName(reinterpret_cast<HMODULE>(dep.iModuleHandle),(LPWSTR)depBuf);
397 TruncToNarrow(depBuf8, depBuf, deplen);
399 TPtrC depp(depBuf8,deplen);
400 if ((ix=depp.LocateReverse('\\'))>=0)
401 depp.Set(depp.Mid(ix+1));
402 #ifndef __REMOVE_PLATSEC_DIAGNOSTICS__
403 TInt r = PlatSec::LoaderCapabilityViolation(mainp, depp, missingCaps);
404 #else //__REMOVE_PLATSEC_DIAGNOSTICS__
405 TInt r = PlatSec::EmitDiagnostic();
406 #endif // !__REMOVE_PLATSEC_DIAGNOSTICS__
416 #pragma warning( default : 4701 ) // enable warning C4701: local variable 'missingCaps' may be used without having been initialized
419 void DModuleList::SetFlags()
421 __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::SetFlags"));
422 TInt c=iModules.Count();
423 SModule* pM=(SModule*)&iModules[0];
427 SModule* pM2=(SModule*)&iModules[0];
428 for (; pM2<pE; ++pM2)
429 pM2->iFlags &= ~EFlagMark;
430 TUint32 flags=Flags(pM);
431 if (flags & EFlagData)
432 pM->iFlags|=EFlagDataPresent;
433 if (flags & EFlagExe)
434 pM->iFlags|=EFlagExeInTree;
435 __KTRACE_OPT(KDLL, Kern::Printf("Module %08x Flags=%08x", pM->iModuleHandle, pM->iFlags));
437 pM=(SModule*)&iModules[0];
441 const TInt* pI=pM->iDepList;
442 const TInt* pIE=pI+c;
448 TUint32 mflags=iModules[ix].iFlags;
449 if ( (mflags&(EFlagDataPresent|EFlagExeInTree)) && !(mflags&EFlagAlwaysLoaded))
453 __KTRACE_OPT(KDLL, Kern::Printf("Module %08x DepCount=%d", pM->iModuleHandle, pM->iDepCount));
457 TUint32 DModuleList::Flags(SModule* aM)
459 TUint32 flags=aM->iFlags;
460 __KTRACE_OPT(KDLL, Kern::Printf(">DModuleList::Flags %08x", aM->iModuleHandle));
461 if ((aM->iFlags & EFlagMark)==0)
463 aM->iFlags |= EFlagMark;
464 const TInt* pI=aM->iDepList;
465 const TInt* pE=pI+iModules.Count();
471 TUint32 mflags=Flags(&iModules[ix]);
477 __KTRACE_OPT(KDLL, Kern::Printf("<DModuleList::Flags %08x = %08x", aM->iModuleHandle, flags));
481 TInt DModuleList::LoadDependencies()
483 __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LoadDependencies"));
484 TInt c=iModules.Count();
485 SModule* pM=(SModule*)&iModules[0];
490 TUint32 flags=pM->iFlags;
491 __KTRACE_OPT(KDLL, Kern::Printf("ModuleHandle %08x flags %08x", pM->iModuleHandle, flags));
492 if (!(flags & (EFlagDataPresent|EFlagExeInTree)) || (flags&EFlagAlwaysLoaded))
495 w32m.iWin32ModuleHandle=(TLinAddr)pM->iModuleHandle;
497 TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
498 __KTRACE_OPT(KDLL, Kern::Printf("GlobalIndex=%d", ix));
499 if (ix<0 && (flags & EFlagExe))
500 return KErrNotSupported; // we never implicitly load an EXE
503 pS=MM::Win32Modules[ix].iCodeSeg;
504 __KTRACE_OPT(KDLL, Kern::Printf("Already loaded; CSEG=%08x %C", pS, pS));
507 pS->iDepCount=pM->iDepCount;
510 pS->iDeps=(DCodeSeg**)Kern::AllocZ(pS->iDepCount*sizeof(DCodeSeg*));
517 if (!(pS->iMark & DCodeSeg::EMarkLdr))
519 pS->iMark |= DCodeSeg::EMarkLdr;
522 pM->iFlags|=EFlagAlreadyLoaded;
527 __KTRACE_OPT(KDLL, Kern::Printf("Create new, depcount=%d", pM->iDepCount));
528 pS=new DWin32CodeSeg;
531 TInt r=pS->CreateAlreadyLoaded((HMODULE)pM->iModuleHandle, pM->iDepCount);
539 pS->iModuleVersion = pM->iModuleVersion;
540 if (iMain->iAttr & ECodeSegAttKernel)
541 pS->iAttr |= ECodeSegAttKernel;
542 if (flags & EFlagData)
544 pS->iMark |= DCodeSeg::EMarkData|DCodeSeg::EMarkDataPresent;
545 if (!(flags&EFlagExe))
546 pS->iMark |= DCodeSeg::EMarkDataInit;
548 if ( (flags & EFlagData) || ((flags&(EFlagExe|EFlagExeInTree))==EFlagExeInTree) )
552 pS->iExeCodeSeg = iAttachProcess->CodeSeg();
553 pS->SetAttachProcess(iAttachProcess);
560 void DModuleList::LinkDependencies()
562 __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::LinkDependencies"));
563 TInt c=iModules.Count();
564 SModule* pM=(SModule*)&iModules[0];
568 DWin32CodeSeg* pS=pM->iCodeSeg;
569 if (!pS || (pM->iFlags&EFlagAlreadyLoaded))
571 const TInt* pI=pM->iDepList;
572 const TInt* pIE=pI+c;
578 DWin32CodeSeg* pD=iModules[ix].iCodeSeg;
580 pS->iDeps[pS->iNextDep++]=pD;
583 pM=(SModule*)&iModules[0];
586 TInt DModuleList::Loaded()
588 __KTRACE_OPT(KDLL, Kern::Printf("DModuleList::Loaded()"));
589 TInt c=iModules.Count();
590 SModule* pM=(SModule*)&iModules[0];
593 for (; pM<pE && r==KErrNone; ++pM)
595 DWin32CodeSeg* pS=pM->iCodeSeg;
598 pS->FinaliseRecursiveFlags();
599 pS->iMark |= DCodeSeg::EMarkLoaded;
604 pM=(SModule*)&iModules[0];
606 pM->iCodeSeg=NULL; // cleanup will occur by EMarkLdr if needed
611 TInt MakeDll(HANDLE aFile)
613 IMAGE_DOS_HEADER dosh;
615 ReadFile(aFile, &dosh, sizeof(dosh), &bytes, NULL);
616 if ( IMAGE_DOS_SIGNATURE != dosh.e_magic )
618 if (dosh.e_lfarlc < sizeof(dosh))
620 SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
621 IMAGE_NT_HEADERS32 peh;
622 ReadFile(aFile, &peh, sizeof(peh), &bytes, NULL);
623 if ( peh.Signature != IMAGE_NT_SIGNATURE )
626 peh.FileHeader.Characteristics |= IMAGE_FILE_DLL;
627 peh.OptionalHeader.AddressOfEntryPoint = 0;
628 SetFilePointer(aFile,dosh.e_lfanew,NULL,FILE_BEGIN);
629 WriteFile(aFile, &peh, sizeof(peh), &bytes, NULL);
633 wchar_t* TempModuleName(const wchar_t* aExe)
635 static TInt ModuleGeneration = 0;
636 static TInt Time = 0;
638 WCHAR ex_[KMaxFileName + 1];
644 Time = st.wSecond + st.wMinute*60 + st.wHour*3600;
647 const char* imagePath = Property::GetString("EmulatorImagePath");
649 while ((*p++ = *imagePath++) != 0)
651 wcscpy(p-1, wcsrchr(aExe, '\\') + 1);
652 p = ex_ + wcslen(ex_);
657 _itow(ModuleGeneration++, p, 10);
661 wchar_t* file = (wchar_t*)Kern::Alloc((p-ex_)*sizeof(WCHAR));
667 DCodeSeg* M::NewCodeSeg(TCodeSegCreateInfo&)
669 // Create a new instance of this class.
673 __KTRACE_OPT(KDLL,Kern::Printf("M::NewCodeSeg"));
674 return new DWin32CodeSeg;
677 DWin32CodeSeg::DWin32CodeSeg()
684 DWin32CodeSeg::~DWin32CodeSeg()
689 __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Destruct %C", this));
690 DBase::Delete(iModuleList);
695 w32m.iWin32ModuleHandle=(TLinAddr)iModuleHandle;
697 TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
701 MM::Win32Modules[ix].iCodeSeg=NULL;
703 MM::Win32Modules.Remove(ix);
705 // Kernel process has to be told to unmap code seg to work round
706 // a problem where failed driver code seg is not unmapped before delete
707 K::TheKernelProcess->UnmapCodeSeg(this);
708 Emulator::FreeLibrary(iWinInstance);
713 Emulator::DeleteFile(iModuleFile);
714 Kern::Free(iModuleFile);
716 Kern::Free(iDataCopy);
717 DCodeSeg::Destruct();
720 TInt DWin32CodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess)
722 __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::DoCreate %C proc %O", this, aProcess));
724 TBool exe=(iExeCodeSeg==this);
725 if (exe && (iAttr&ECodeSegAttKernel))
728 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN"));
729 TUint16 fileNameW[KMaxFileName];
730 ExpandToWide(fileNameW, iFileName->Ptr(), iFileName->Length());
731 fileNameW[iFileName->Length()] = '\0';
732 iWinInstance = Emulator::LoadLibrary((LPCWSTR)fileNameW);
733 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EKERN %08x", iWinInstance));
736 if (aInfo.iTotalDataSize)
737 iMark|=EMarkData|EMarkDataPresent;
739 KernelModuleHandle=Emulator::GetModuleHandle((LPCWSTR)fileNameW);
740 return RegisterCodeSeg(KernelModuleHandle);
742 TWin32Filename w32fn(*iFileName);
743 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : w32fn=%S",iFileName))
744 DWin32Process* p=(DWin32Process*)aProcess;
747 HMODULE h = Emulator::GetModuleHandle(w32fn);
748 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : h=%08x exe=%08x",h,exe));
751 if (h == GetModuleHandleA(NULL))
753 // This was the executable that was used to run the emulator
754 // so all relocations will be valid and we can use it
755 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : initial exe"));
757 goto makecopy; // we can only do this once however
758 iWinInstance = Emulator::LoadLibrary(w32fn);
759 BootComplete = ETrue;
762 r=KErrAlreadyExists; // can't load same EXEXP twice
766 // Already loaded DLL
767 // Code segment doesn't exist so create it
768 __KTRACE_OPT(KDLL,Kern::Printf("Already loaded, module %08x",h));
769 iWinInstance = Emulator::LoadLibrary(w32fn);
771 else if (iAttr & ECodeSegAttHDll)
773 // EXE with exports (EXEXP target) - can only have one instance
774 // or DLL not already loaded
775 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : EXEXP or new DLL"));
776 iWinInstance = Emulator::LoadLibrary(w32fn);
778 h=Emulator::GetModuleHandle(w32fn);
782 // EXE with no exports. In order that multiple instances of the EXE may be run,
783 // we make a copy of the EXE file to a name which is unique across instances,
784 // set the DLL flag and load it as a DLL.
786 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : MakeCopy"));
788 iModuleFile = TempModuleName(w32fn);
791 else if (Emulator::CopyFile(w32fn,iModuleFile,FALSE))
793 DWORD fattr = Emulator::GetFileAttributes(iModuleFile);
794 if (fattr != 0xffffffff && Emulator::SetFileAttributes(iModuleFile, fattr & ~FILE_ATTRIBUTE_READONLY))
796 HANDLE f = Emulator::CreateFile(iModuleFile,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL);
797 if (INVALID_HANDLE_VALUE != f)
803 iWinInstance = Emulator::LoadLibrary(iModuleFile);
805 h=Emulator::GetModuleHandle(iModuleFile);
811 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d iWinInstance=%08x",__LINE__,r,iWinInstance));
812 if (r==KErrNone && !iWinInstance)
813 r=Emulator::LastError();
814 __KTRACE_OPT(KDLL,Kern::Printf("W32CodeSeg : line %d r=%d",__LINE__,r));
817 const char* entry_name = exe ? "_E32Startup" : "_E32Dll" ;
818 aInfo.iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, entry_name);
819 if (!aInfo.iFileEntryPoint)
825 r=RegisterCodeSeg(h);
833 if (r==KErrNone && aInfo.iTotalDataSize && !iAlwaysLoaded)
835 iMark|=EMarkData|EMarkDataPresent;
837 iMark|=EMarkDataInit;
842 __KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
847 TInt DWin32CodeSeg::RegisterCodeSeg(HMODULE aModule)
849 __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %C RegisterCodeSeg(%08x)", this, aModule));
850 Emulator::TModule etm(aModule);
851 const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
852 iRunAddress = (TLinAddr)aModule;
853 iSize = nth->OptionalHeader.SizeOfImage;
855 w32m.iWin32ModuleHandle=(TLinAddr)aModule;
858 TInt ix=MM::Win32Modules.FindInUnsignedKeyOrder(w32m);
861 SWin32Module& wmr=MM::Win32Modules[ix];
862 __ASSERT_ALWAYS(!wmr.iCodeSeg, MM::Panic(MM::EInvalidSharedModule));
867 r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
870 iModuleHandle=aModule;
871 iCodeSegId=++MM::NextCodeSegId;
876 TInt DWin32CodeSeg::CreateAlreadyLoaded(HMODULE aModule, TInt aDepCount)
878 __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg %08x CreateAlreadyLoaded(%08x,%d)", this, aModule, aDepCount));
879 Emulator::TModule etm(aModule);
881 TInt32 uid1=iUids.iUid[0].iUid;
882 if (uid1!=KDynamicLibraryUidValue) // only implicitly load DLLs
883 return KErrNotSupported;
885 WCHAR name[MAX_PATH+1];
886 TInt r=Emulator::GetModuleFileName(aModule, name);
888 return Emulator::LastError();
889 TUint8 name8[MAX_PATH+1];
890 TruncToNarrow(name8,(const TUint16*)name,-1);
893 __KTRACE_OPT(KDLL, Kern::Printf("Loading library %s", name8));
895 TPtrC fpptr((const TText*)name8);
896 TInt slash=fpptr.LocateReverse('\\');
897 TPtrC nptr=fpptr.Mid(slash+1);
898 iFileName=HBuf::New(nptr);
901 iRootName.Set(*iFileName);
902 iExtOffset = iFileName->LocateReverse('.');
903 if (iExtOffset==KErrNotFound)
904 iExtOffset = iFileName->Length();
905 iModuleVersion = 0x00010000u;
909 iDeps=(DCodeSeg**)Kern::AllocZ(iDepCount*sizeof(DCodeSeg*));
913 iWinInstance = Emulator::LoadLibrary(name);
915 return Emulator::LastError();
916 iFileEntryPoint = (TLinAddr)Emulator::GetProcAddress(iWinInstance, "_E32Dll");
917 if (!iFileEntryPoint)
918 return KErrNotSupported;
919 iEntryPtVeneer = iFileEntryPoint;
920 r=RegisterCodeSeg(aModule);
924 r = CodeSegsByName.InsertInOrderAllowRepeats(this, &CompareCodeSegsByName);
926 r = CodeSegsByAddress.Add(this);
929 GlobalList.Add(&iLink);
930 iAsyncDeleteNext=this;
932 __KTRACE_OPT(KDLL, DumpWin32CodeSeg(*this));
936 TInt DWin32CodeSeg::CopyDataBss()
938 __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::CopyDataBss()"));
940 Emulator::TModule etm(iModuleHandle);
941 const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
942 if (!(hdr->iFlags & KEmulatorImageFlagAllowDllData))
944 const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
945 const IMAGE_SECTION_HEADER* bss=etm.SectionHeader(KWin32SectionName_EpocBss);
948 iRealDataSize = data->Misc.VirtualSize;
949 iDataDest = (TLinAddr)etm.Translate(data->VirtualAddress);
950 iDataCopy = Kern::Alloc(iRealDataSize);
953 memcpy(iDataCopy, (const TAny*)iDataDest, iRealDataSize);
957 iRealBssSize = bss->Misc.VirtualSize;
958 iBssDest = (TLinAddr)etm.Translate(bss->VirtualAddress);
963 TInt DWin32CodeSeg::ProcessImports(DProcess* aProcess)
965 __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::ProcessImports(%O)", aProcess));
966 iModuleList=new DModuleList(this, aProcess);
969 TInt r=iModuleList->GatherDependencies(iModuleHandle);
972 TInt ix=iModuleList->Find((TInt)iModuleHandle);
973 DModuleList::SModule& mm=iModuleList->iModules[ix];
974 r=iModuleList->CompileDepLists();
977 iModuleList->SetFlags();
978 r=iModuleList->LoadDependencies();
981 if ((mm.iFlags&(DModuleList::EFlagDataPresent|DModuleList::EFlagExeInTree)) && !(mm.iFlags&DModuleList::EFlagAlwaysLoaded))
985 iExeCodeSeg=aProcess->CodeSeg();
986 SetAttachProcess(aProcess);
989 iModuleList->LinkDependencies();
995 TInt DWin32CodeSeg::Loaded(TCodeSegCreateInfo& aInfo)
997 __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded()"));
1001 r=iModuleList->Loaded();
1004 DBase::Delete(iModuleList);
1009 r=DCodeSeg::Loaded(aInfo);
1010 __KTRACE_OPT(KDLL, Kern::Printf("DWin32CodeSeg::Loaded() - %d", r));
1014 void DWin32CodeSeg::ReadExportDir(TUint32*)
1019 TBool DWin32CodeSeg::FindCheck(DProcess* /*aProcess*/)
1021 // We never create multiple copies of the same code segment,
1022 // so if code segment exists, allow it to be found.
1023 // CodeSegOpen will fail if it is incompatible.
1027 TBool DWin32CodeSeg::OpenCheck(DProcess* aProcess)
1029 __KTRACE_OPT(KDLL,Kern::Printf("CSEG:%08x Compat? proc=%O",this,aProcess));
1031 return EFalse; // never reuse EXE code segments
1035 TLibraryFunction DWin32CodeSeg::Lookup(TInt aOrdinal)
1037 // Find an exported function by ordinal
1040 TLibraryFunction f = NULL;
1044 f = (TLibraryFunction)Emulator::GetProcAddress(iWinInstance, (const char *)aOrdinal);
1045 if ((TLinAddr)f == iFileEntryPoint)
1050 // Find 0th Ordinal, which should be named symbol export data, from named data segment
1051 Emulator::TModule etm(iModuleHandle);
1052 f = (TLibraryFunction)etm.Section(KWin32SectionName_NmdExpData);
1054 __KTRACE_OPT(KDLL,Kern::Printf("DWin32CodeSeg::Lookup(%d)->%08x",aOrdinal,f));
1058 DCodeSeg* DCodeSeg::FindRomCode(const TAny*)
1064 void DWin32CodeSeg::InitData()
1068 TInt DWin32CodeSeg::GetMemoryInfo(TModuleMemoryInfo&, DProcess*)
1070 return KErrNotSupported;
1073 void DWin32CodeSeg::Info(TCodeSegCreateInfo& aInfo)
1075 Emulator::TModule etm(iModuleHandle);
1076 const IMAGE_NT_HEADERS32* nth=etm.NtHeader();
1077 const IMAGE_EXPORT_DIRECTORY* exd=
1078 (const IMAGE_EXPORT_DIRECTORY*)etm.Translate(nth->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
1079 const TEmulatorImageHeader* hdr = (const TEmulatorImageHeader*)etm.Section(KWin32SectionName_Symbian);
1080 TBool isExe = hdr && hdr->iUids[0].iUid==KExecutableImageUidValue;
1081 const IMAGE_SECTION_HEADER* text=etm.SectionHeader(KWin32SectionName_Text);
1082 const IMAGE_SECTION_HEADER* rdata=etm.SectionHeader(KWin32SectionName_RData);
1083 const IMAGE_SECTION_HEADER* data=etm.SectionHeader(KWin32SectionName_EpocData);
1084 if (!isExe && !(hdr->iFlags & KEmulatorImageFlagAllowDllData))
1086 aInfo.iTextSize=text->Misc.VirtualSize;
1087 aInfo.iCodeSize=text->Misc.VirtualSize;
1089 aInfo.iCodeSize+=rdata->Misc.VirtualSize;
1090 aInfo.iDataSize=data ? (data->SizeOfRawData) : 0;
1091 aInfo.iBssSize=data ? (data->Misc.VirtualSize-data->SizeOfRawData) : 0;
1092 aInfo.iTotalDataSize=aInfo.iDataSize+aInfo.iBssSize;
1093 aInfo.iExportDir=(TLinAddr)exd;
1094 aInfo.iExportDirCount=exd ? exd->NumberOfFunctions : 0;
1095 aInfo.iCodeLoadAddress=(TLinAddr)etm.Translate(text->VirtualAddress);
1096 aInfo.iCodeRunAddress=aInfo.iCodeLoadAddress;
1097 aInfo.iDataLoadAddress=data ? (TLinAddr)etm.Translate(data->VirtualAddress) : 0;
1098 aInfo.iDataRunAddress=aInfo.iDataLoadAddress;
1099 DCodeSeg::Info(aInfo);
1102 TLinAddr DCodeSeg::ExceptionDescriptor()
1104 return 0; // not used on emulator
1107 TInt MM::RegisterModule(HMODULE aModule)
1109 __KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule %08x",aModule));
1111 w32m.iWin32ModuleHandle=(TLinAddr)aModule;
1113 TInt r=MM::Win32Modules.InsertInUnsignedKeyOrder(w32m);
1114 __KTRACE_OPT(KBOOT, Kern::Printf("MM::RegisterModule ret %d",r));
1118 _LIT(KRomSysBin, "Z:\\sys\\bin");
1120 // Massage file names returned for stuff in EPOCROOT\epoc32\release\wins\xxxx\
1121 // in order to make them appear to be in z:\system\libs
1122 void P::NormalizeExecutableFileName(TDes& a)
1124 __KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName %lS", &a));
1125 if (a.Length()<3 || a[1]!=':' || a[2]!='\\')
1127 // don't have a drive so assume in 'ROM'
1128 TFileName initial(a);
1130 if (initial.Length()==0 || initial[0]!='\\')
1133 __KTRACE_OPT(KDLL, Kern::Printf("NormalizeExecutableFileName -> %lS", &a));
1137 TInt LookupDllUid(TInt aModule)
1139 TInt r = KDllUid_Default;
1142 w32m.iWin32ModuleHandle=(TLinAddr)aModule;
1144 MM::Win32Modules.SpecificFindInUnsignedKeyOrder(w32m, ix, EArrayFindMode_Last);
1147 DWin32CodeSeg* pS = MM::Win32Modules[ix-1].iCodeSeg;
1148 if (pS && pS->iFileEntryPoint==(TLinAddr)aModule)
1151 Kern::EndAccessCode();