|
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". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // e32\memmodel\epoc\pcodeseg.cpp |
|
15 // |
|
16 // |
|
17 |
|
18 #include "plat_priv.h" |
|
19 #include <e32uid.h> |
|
20 |
|
21 TLinAddr DCodeSeg::ExceptionDescriptor() |
|
22 { |
|
23 DEpocCodeSeg* s = (DEpocCodeSeg*)this; |
|
24 if (s->iXIP) |
|
25 return s->RomInfo().iExceptionDescriptor; |
|
26 return s->RamInfo().iExceptionDescriptor; |
|
27 } |
|
28 |
|
29 DEpocCodeSeg::~DEpocCodeSeg() |
|
30 { |
|
31 if (!iXIP && iMemory) |
|
32 { |
|
33 iMemory->iCodeSeg = 0; |
|
34 iMemory->Close(); |
|
35 iMemory = NULL; |
|
36 } |
|
37 } |
|
38 |
|
39 void DEpocCodeSeg::Destruct() |
|
40 { |
|
41 DCodeSeg::Wait(); |
|
42 |
|
43 if (iLoaderCookie!=NULL) |
|
44 { |
|
45 if ((TInt) iLoaderCookie&1) // Not set fully loaded |
|
46 { |
|
47 iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) & ~1); |
|
48 delete iLoaderCookie; |
|
49 iLoaderCookie=NULL; |
|
50 } |
|
51 else |
|
52 { |
|
53 // Notify reaper of destruction |
|
54 NKern::LockSystem(); |
|
55 if (DestructNotifyRequest->IsReady()) |
|
56 { |
|
57 DThread* t = DestructNotifyThread; |
|
58 DestructNotifyThread = NULL; |
|
59 Kern::QueueRequestComplete(t, DestructNotifyRequest,KErrNone); |
|
60 } |
|
61 NKern::UnlockSystem(); |
|
62 |
|
63 iLoaderCookie->iNext=DestructNotifyList; |
|
64 DestructNotifyList=iLoaderCookie; |
|
65 iLoaderCookie=NULL; |
|
66 } |
|
67 } |
|
68 |
|
69 DCodeSeg::Signal(); |
|
70 DCodeSeg::Destruct(); |
|
71 } |
|
72 |
|
73 void DEpocCodeSeg::Info(TCodeSegCreateInfo& aInfo) |
|
74 { |
|
75 CHECK_PAGING_SAFE; |
|
76 if (iXIP) |
|
77 { |
|
78 const TRomImageHeader& rih=RomInfo(); |
|
79 aInfo.iCodeSize=rih.iCodeSize; |
|
80 aInfo.iTextSize=rih.iTextSize; |
|
81 aInfo.iDataSize=rih.iDataSize; |
|
82 aInfo.iBssSize=rih.iBssSize; |
|
83 aInfo.iTotalDataSize=rih.iTotalDataSize; |
|
84 aInfo.iExportDir=rih.iExportDir; |
|
85 aInfo.iExportDirCount=rih.iExportDirCount; |
|
86 aInfo.iCodeLoadAddress=rih.iCodeAddress; |
|
87 aInfo.iCodeRunAddress=rih.iCodeAddress; |
|
88 aInfo.iDataLoadAddress=rih.iDataAddress; |
|
89 aInfo.iDataRunAddress=rih.iDataBssLinearBase; |
|
90 aInfo.iExceptionDescriptor = rih.iExceptionDescriptor; |
|
91 } |
|
92 else |
|
93 { |
|
94 const SRamCodeInfo& ri=RamInfo(); |
|
95 aInfo.iCodeSize=ri.iCodeSize; |
|
96 aInfo.iTextSize=ri.iTextSize; |
|
97 aInfo.iDataSize=ri.iDataSize; |
|
98 aInfo.iBssSize=ri.iBssSize; |
|
99 aInfo.iTotalDataSize=ri.iDataSize+ri.iBssSize; |
|
100 aInfo.iExportDir=ri.iExportDir; |
|
101 aInfo.iExportDirCount=ri.iExportDirCount; |
|
102 aInfo.iCodeLoadAddress=ri.iCodeLoadAddr; |
|
103 aInfo.iCodeRunAddress=ri.iCodeRunAddr; |
|
104 aInfo.iDataLoadAddress=ri.iDataLoadAddr; |
|
105 aInfo.iDataRunAddress=ri.iDataRunAddr; |
|
106 aInfo.iExceptionDescriptor = ri.iExceptionDescriptor; |
|
107 } |
|
108 DCodeSeg::Info(aInfo); |
|
109 } |
|
110 |
|
111 void DEpocCodeSeg::GetDataSizeAndBase(TInt& aTotalDataSizeOut, TLinAddr& aDataBaseOut) |
|
112 { |
|
113 if (iXIP) |
|
114 { |
|
115 aTotalDataSizeOut=RomInfo().iTotalDataSize; |
|
116 aDataBaseOut=RomInfo().iDataBssLinearBase; |
|
117 } |
|
118 else |
|
119 { |
|
120 aTotalDataSizeOut=RamInfo().iDataSize+RamInfo().iBssSize; |
|
121 aDataBaseOut=RamInfo().iDataRunAddr; |
|
122 } |
|
123 } |
|
124 |
|
125 TLibraryFunction DEpocCodeSeg::Lookup(TInt aOrdinal) |
|
126 { |
|
127 CHECK_PAGING_SAFE; |
|
128 // return NULL for -ve ordinal or 0th ordinal when not stddll/stdexe |
|
129 if (aOrdinal<0 || (aOrdinal==0 && !(iAttr&ECodeSegAttNmdExpData))) |
|
130 return NULL; |
|
131 TInt xdc; |
|
132 TLinAddr* xd; // points to the 0th ordinal of export table |
|
133 if (iXIP) |
|
134 { |
|
135 const TRomImageHeader& rih=RomInfo(); |
|
136 xdc=rih.iExportDirCount; |
|
137 xd=(TLinAddr*)rih.iExportDir - 1; |
|
138 } |
|
139 else |
|
140 { |
|
141 SRamCodeInfo& ri=RamInfo(); |
|
142 xdc=ri.iExportDirCount; |
|
143 xd=(TLinAddr*)ri.iExportDir - 1; |
|
144 } |
|
145 if (aOrdinal <= xdc) |
|
146 { |
|
147 UNLOCK_USER_MEMORY(); |
|
148 TLibraryFunction f=(TLibraryFunction)xd[aOrdinal]; |
|
149 LOCK_USER_MEMORY(); |
|
150 if ((TLinAddr)f == iFileEntryPoint) |
|
151 f = NULL; |
|
152 __KTRACE_OPT(KDLL,Kern::Printf("Lookup(%d)->%08x",aOrdinal,f)); |
|
153 return f; |
|
154 } |
|
155 __KTRACE_OPT(KDLL,Kern::Printf("Lookup(%d)->NULL",aOrdinal)); |
|
156 return NULL; |
|
157 } |
|
158 |
|
159 TInt DEpocCodeSeg::GetMemoryInfo(TModuleMemoryInfo& aInfo, DProcess*) |
|
160 { |
|
161 CHECK_PAGING_SAFE; |
|
162 if (iXIP) |
|
163 { |
|
164 const TRomImageHeader& rih = RomInfo(); |
|
165 aInfo.iCodeBase = rih.iCodeAddress; |
|
166 aInfo.iCodeSize = rih.iTextSize; |
|
167 aInfo.iConstDataSize = rih.iCodeSize - aInfo.iCodeSize; |
|
168 aInfo.iConstDataBase = (aInfo.iConstDataSize > 0) ? (aInfo.iCodeBase + aInfo.iCodeSize) : 0; |
|
169 aInfo.iInitialisedDataBase = rih.iDataBssLinearBase; |
|
170 aInfo.iInitialisedDataSize = rih.iDataSize; |
|
171 aInfo.iUninitialisedDataSize = rih.iBssSize; |
|
172 aInfo.iUninitialisedDataBase = aInfo.iInitialisedDataBase+aInfo.iInitialisedDataSize; |
|
173 } |
|
174 else |
|
175 { |
|
176 const SRamCodeInfo& ri = RamInfo(); |
|
177 aInfo.iCodeBase = ri.iCodeRunAddr; |
|
178 aInfo.iCodeSize = ri.iTextSize; |
|
179 aInfo.iConstDataSize = ri.iCodeSize - aInfo.iCodeSize; |
|
180 aInfo.iConstDataBase = (aInfo.iConstDataSize > 0) ? (aInfo.iCodeBase + aInfo.iCodeSize) : 0; |
|
181 aInfo.iInitialisedDataBase = ri.iDataRunAddr; |
|
182 aInfo.iInitialisedDataSize = ri.iDataSize; |
|
183 aInfo.iUninitialisedDataSize = ri.iBssSize; |
|
184 aInfo.iUninitialisedDataBase = aInfo.iInitialisedDataBase + aInfo.iInitialisedDataSize; |
|
185 } |
|
186 return KErrNone; |
|
187 } |
|
188 |
|
189 //const TUint32 KRomImageFlagsAlwaysLoaded=KRomImageFlagPrimary|KRomImageFlagVariant|KRomImageFlagExtension; |
|
190 const TUint32 KRomImageDataFlags=(KRomImageFlagData|KRomImageFlagDataInit|KRomImageFlagDataPresent); |
|
191 TInt DEpocCodeSeg::DoCreate(TCodeSegCreateInfo& aInfo, DProcess* aProcess) |
|
192 { |
|
193 __KTRACE_OPT(KDLL,Kern::Printf(">DEpocCodeSeg::DoCreate code_addr=%08x",aInfo.iCodeLoadAddress)); |
|
194 CHECK_PAGING_SAFE; |
|
195 TInt r=KErrNone; |
|
196 TBool exeSeg=(iExeCodeSeg==this); |
|
197 TBool kp=exeSeg && (aProcess->iAttributes&DProcess::ESupervisor); |
|
198 TBool user_proc=exeSeg && !kp; |
|
199 if (aInfo.iCodeLoadAddress) |
|
200 { |
|
201 iXIP=ETrue; |
|
202 iInfo=(const TAny*)aInfo.iCodeLoadAddress; |
|
203 } |
|
204 if (user_proc) |
|
205 { |
|
206 r=aProcess->CreateDataBssStackArea((TProcessCreateInfo&)aInfo); |
|
207 if (r!=KErrNone) |
|
208 return r; |
|
209 } |
|
210 if (iXIP) |
|
211 { |
|
212 const TRomImageHeader& rih=RomInfo(); |
|
213 iXIP=ETrue; |
|
214 if ( (rih.iFlags & (KRomImageFlagExeInTree|KRomImageFlagDll)) == (KRomImageFlagExeInTree|KRomImageFlagDll)) |
|
215 { |
|
216 const TRomImageHeader* exeRIH=rih.iDllRefTable->iEntry[0]; // EXE is always first entry |
|
217 if (aProcess) |
|
218 { |
|
219 DEpocCodeSeg* pS=(DEpocCodeSeg*)aProcess->CodeSeg(); |
|
220 if (!pS->iXIP || &pS->RomInfo()!=exeRIH) |
|
221 return KErrNotSupported; |
|
222 iExeCodeSeg=pS; |
|
223 } |
|
224 } |
|
225 |
|
226 iMark |= (rih.iFlags & KRomImageDataFlags); |
|
227 iMark |= EMarkRecursiveFlagsValid; |
|
228 __KTRACE_OPT(KDLL,Kern::Printf("ROM Code Seg: mark %08x attr=%02x",iMark,iAttr)); |
|
229 aInfo.iFileEntryPoint=rih.iEntryPoint; |
|
230 aInfo.iExportDir=rih.iExportDir; |
|
231 aInfo.iCodeLoadAddress=rih.iCodeAddress; |
|
232 aInfo.iCodeRunAddress=rih.iCodeAddress; |
|
233 iRunAddress = rih.iCodeAddress; |
|
234 iSize = rih.iCodeSize; |
|
235 aInfo.iDataLoadAddress=rih.iDataAddress; |
|
236 if (aInfo.iTotalDataSize && user_proc && aProcess->iDataBssRunAddress!=rih.iDataBssLinearBase) |
|
237 K::Fault(K::EProcessDataAddressInvalid); |
|
238 aInfo.iDataRunAddress=rih.iDataBssLinearBase; |
|
239 aInfo.iExceptionDescriptor = rih.iExceptionDescriptor; |
|
240 r=DoCreateXIP(aProcess); |
|
241 return r; |
|
242 } |
|
243 iMemory = DEpocCodeSegMemory::New(this); |
|
244 if (!iMemory) |
|
245 return KErrNoMemory; |
|
246 iInfo = &iMemory->iRamInfo; |
|
247 |
|
248 if (aInfo.iUseCodePaging) |
|
249 { |
|
250 if ((aInfo.iCodeBlockMapEntries==NULL) || (aInfo.iCodeBlockMapCommon.iLocalDriveNumber<0) || |
|
251 (((TInt64) (aInfo.iFileClamp.iCookie[0] | aInfo.iFileClamp.iCookie[1]))==0)) |
|
252 return KErrArgument; |
|
253 |
|
254 iLoaderCookie = new TCodeSegLoaderCookieList(); |
|
255 if (!iLoaderCookie) |
|
256 return KErrNoMemory; |
|
257 |
|
258 SBlockMapInfoBase* cbm = &aInfo.iCodeBlockMapCommon; |
|
259 |
|
260 TUint startBlock; |
|
261 kumemget32(&startBlock, &aInfo.iCodeBlockMapEntries->iStartBlock, sizeof(TUint)); |
|
262 |
|
263 iLoaderCookie->iCookie.iDriveNumber = cbm->iLocalDriveNumber; |
|
264 iLoaderCookie->iCookie.iStartAddress = cbm->iStartBlockAddress + |
|
265 startBlock * |
|
266 cbm->iBlockGranularity + |
|
267 cbm->iBlockStartOffset; |
|
268 iLoaderCookie->iCookie.iFileClamp = aInfo.iFileClamp; |
|
269 // Mark cookie not to be closed yet |
|
270 iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) | 1); |
|
271 } |
|
272 |
|
273 SRamCodeInfo& ri=RamInfo(); |
|
274 ri.iCodeSize=aInfo.iCodeSize; |
|
275 ri.iTextSize=aInfo.iTextSize; |
|
276 ri.iDataSize=aInfo.iDataSize; |
|
277 ri.iBssSize=aInfo.iBssSize; |
|
278 TInt total_data_size=ri.iDataSize+ri.iBssSize; |
|
279 ri.iExportDirCount=aInfo.iExportDirCount; |
|
280 if (total_data_size!=0) |
|
281 { |
|
282 iMark|=(EMarkData|EMarkDataPresent); |
|
283 if (!exeSeg) |
|
284 iMark|=EMarkDataInit; |
|
285 } |
|
286 // if this DLL/EXE doesn't have data, don't set valid bit since we don't yet know about its dependencies |
|
287 |
|
288 if (exeSeg) |
|
289 ri.iDataRunAddr=aProcess->iDataBssRunAddress; |
|
290 r=DoCreateRam(aInfo, aProcess); |
|
291 if (r==KErrNone) |
|
292 { |
|
293 aInfo.iFileEntryPoint+=ri.iCodeRunAddr; |
|
294 aInfo.iExportDir+=ri.iCodeRunAddr; |
|
295 ri.iExportDir=aInfo.iExportDir; |
|
296 aInfo.iCodeLoadAddress=ri.iCodeLoadAddr; |
|
297 aInfo.iCodeRunAddress=ri.iCodeRunAddr; |
|
298 aInfo.iDataLoadAddress=ri.iDataLoadAddr; |
|
299 aInfo.iDataRunAddress=ri.iDataRunAddr; |
|
300 TUint32 xd = aInfo.iExceptionDescriptor; |
|
301 ri.iExceptionDescriptor = xd ? (xd + ri.iCodeRunAddr) : 0; |
|
302 aInfo.iExceptionDescriptor = ri.iExceptionDescriptor; |
|
303 iRunAddress = ri.iCodeRunAddr; |
|
304 } |
|
305 __KTRACE_OPT(KDLL,Kern::Printf("RAM Code Seg: mark %08x attr=%02x xd=%08x",iMark,iAttr,ri.iExceptionDescriptor)); |
|
306 __KTRACE_OPT(KDLL,Kern::Printf("<DEpocCodeSeg::DoCreate %d",r)); |
|
307 return r; |
|
308 } |
|
309 |
|
310 void DEpocCodeSeg::InitData() |
|
311 { |
|
312 __KTRACE_OPT(KDLL,Kern::Printf("DEpocCodeSeg::InitData %C", this)); |
|
313 CHECK_PAGING_SAFE; |
|
314 TInt bss_size=0; |
|
315 TInt data_size=0; |
|
316 TUint8* data_run_ptr=0; |
|
317 const TUint8* data_load_ptr=0; |
|
318 if (iXIP) |
|
319 { |
|
320 const TRomImageHeader& rih=RomInfo(); |
|
321 bss_size=rih.iBssSize; |
|
322 data_size=rih.iDataSize; |
|
323 data_run_ptr=(TUint8*)rih.iDataBssLinearBase; |
|
324 data_load_ptr=(const TUint8*)rih.iDataAddress; |
|
325 } |
|
326 else |
|
327 { |
|
328 SRamCodeInfo& ri=RamInfo(); |
|
329 bss_size=ri.iBssSize; |
|
330 data_size=ri.iDataSize; |
|
331 data_run_ptr=(TUint8*)ri.iDataRunAddr; |
|
332 data_load_ptr=(const TUint8*)ri.iDataLoadAddr; |
|
333 } |
|
334 UNLOCK_USER_MEMORY(); |
|
335 if (data_size) |
|
336 memcpy(data_run_ptr, data_load_ptr, data_size); |
|
337 if (bss_size) |
|
338 memclr(data_run_ptr+data_size, bss_size); |
|
339 LOCK_USER_MEMORY(); |
|
340 } |
|
341 |
|
342 DCodeSeg* DCodeSeg::FindRomCode(const TAny* aRomImgHdr) |
|
343 { |
|
344 CHECK_PAGING_SAFE; |
|
345 const TRomImageHeader& rih = *(const TRomImageHeader*)aRomImgHdr; |
|
346 TLinAddr ca = rih.iCodeAddress; |
|
347 return CodeSegsByAddress.Find(ca); |
|
348 } |
|
349 |
|
350 void P::NormalizeExecutableFileName(TDes& /*aFileName*/) |
|
351 { |
|
352 } |
|
353 |
|
354 TInt DEpocCodeSeg::Loaded(TCodeSegCreateInfo& aInfo) |
|
355 { |
|
356 iLoaderCookie = (TCodeSegLoaderCookieList*) ( ((TInt) iLoaderCookie) & ~1); |
|
357 return DCodeSeg::Loaded(aInfo); |
|
358 } |
|
359 |
|
360 |
|
361 // |
|
362 // DEpocCodeSegMemory |
|
363 // |
|
364 |
|
365 DEpocCodeSegMemory::DEpocCodeSegMemory(DEpocCodeSeg* aCodeSeg) |
|
366 : iAccessCount(1), iCodeSeg(aCodeSeg) |
|
367 { |
|
368 } |
|
369 |
|
370 |
|
371 TInt DEpocCodeSegMemory::Open() |
|
372 { |
|
373 return __e32_atomic_tas_ord32(&iAccessCount, 1, 1, 0) ? KErrNone : KErrGeneral; |
|
374 } |
|
375 |
|
376 |
|
377 TInt DEpocCodeSegMemory::Close() |
|
378 { |
|
379 if (__e32_atomic_tas_ord32(&iAccessCount, 1, -1, 0) == 1) |
|
380 { |
|
381 AsyncDelete(); |
|
382 return DObject::EObjectDeleted; |
|
383 } |
|
384 return 0; |
|
385 } |
|
386 |
|
387 |