userlibandfileserver/fileserver/sfile/sf_lepoc.cpp
branchRCL_3
changeset 21 e7d2d738d3c2
parent 0 a41df078684a
child 39 2bb754abd467
equal deleted inserted replaced
20:597aaf25e343 21:e7d2d738d3c2
   200 	User::Free(subBlocks);
   200 	User::Free(subBlocks);
   201 
   201 
   202 #ifdef _DEBUG
   202 #ifdef _DEBUG
   203 	__IF_DEBUG(Printf("processed reloc table (size=%d,pageCount=%d)", iCodeRelocTableSize, pageCount));
   203 	__IF_DEBUG(Printf("processed reloc table (size=%d,pageCount=%d)", iCodeRelocTableSize, pageCount));
   204 
   204 
   205 	// dump the import fixup table if loader tracing enabled
   205 	// Dump the processed reloc table if loader tracing enabled. The dump is in
   206 	const TUint16* table16 = (const TUint16*)table;
   206 	// two parts; first, the page indexes (1 word per page), then the entries
   207 	const TInt halfWordsInTable = iCodeRelocTableSize / 2;
   207 	// describing the items to be relocated on each of these pages, formatted
   208 	for(i = 0; i < halfWordsInTable; i += 4)
   208 	// with up to 8 entries per line but starting a new line for each page.
   209 		{
   209 	// Each of these entries has the relocation type in the first nibble, and
   210 		__IF_DEBUG(Printf(
   210 	// the offset within the page in the remaining 3 nibbles.
   211 			"reloc %04x: %04x %04x %04x %04x",
   211 	const TUint32* table32 = (const TUint32*)table;
   212 			i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
   212 	for (i = 0; i <= pageCount; ++i)
       
   213 		__IF_DEBUG(Printf("%04x: %08x", i*4, table32[i]));
       
   214 
       
   215 	for (i = 0; i < pageCount; ++i)
       
   216 		{
       
   217 		TUint start = table32[i];
       
   218 		TInt nbytes = table32[i+1] - start;
       
   219 		while (nbytes)
       
   220 			{
       
   221 			TBuf8<0x100> buf;
       
   222 			buf.Format(_L8("%04x:"), start);
       
   223 
       
   224 			const TUint16* p = (const TUint16*)(table+start);
       
   225 			TInt n = nbytes <= 16 ? nbytes : 16;
       
   226 			for (nbytes -= n, start += n; n > 0; n -= 2)
       
   227 				buf.AppendFormat(_L8(" %04x"), *p++);
       
   228 
       
   229 			buf.AppendFormat(_L8("\r\n"));
       
   230 			__IF_DEBUG(RawPrint(buf));
       
   231 			}
   213 		}
   232 		}
   214 #endif
   233 #endif
   215 	return KErrNone;
   234 	return KErrNone;
   216 	}
   235 	}
   217 
   236 
   266 		ExecuteInSupervisorModeVector = UserSvr::ExecuteInSupervisorMode;
   285 		ExecuteInSupervisorModeVector = UserSvr::ExecuteInSupervisorMode;
   267 		gExecutesInSupervisorMode = ETrue;
   286 		gExecutesInSupervisorMode = ETrue;
   268 		}
   287 		}
   269 	}
   288 	}
   270 
   289 
       
   290 // A version that will work in user or supervisor mode
       
   291 void MyPrintf(const char* aFmt, ...)
       
   292 	{
       
   293 	VA_LIST list;
       
   294 	VA_START(list, aFmt);
       
   295 	TPtrC8 fmt((const TText8*)aFmt);
       
   296 	TBuf8<0x100> buf;
       
   297 	buf.AppendFormatList(fmt, list);
       
   298 	buf.AppendFormat(_L8("\r\n"));
       
   299 	RDebug::RawPrint(buf);
       
   300 	VA_END(list);
       
   301 	}
   271 
   302 
   272 /**
   303 /**
   273 Arguments for svRelocateSection.
   304 Arguments for svRelocateSection.
   274 
   305 
   275 The relocation information (at iRelocsBuf) has list sub blocks, each referring to a 4kB
   306 The relocation information (at iRelocsBuf) has list sub blocks, each referring to a 4kB
   338 	}
   369 	}
   339 
   370 
   340 
   371 
   341 /**
   372 /**
   342 Fix up the export directory
   373 Fix up the export directory
   343 Only performed on PE images.  ELF image's exports are marked
   374 Only performed on PE images.  ELF image's exports are marked as relocatable
   344 as relocatable and therefore relocated by svRelocateSection when the 
   375 and therefore relocated by svRelocateSection along with the text section
   345 text section is relocated up
       
   346 */
   376 */
   347 TInt svRelocateExports(TAny* aPtr)
   377 TInt svRelocateExports(TAny* aPtr)
   348 	{
   378 	{
   349 	E32Image* pI=(E32Image*)aPtr;
   379 	E32Image& exporter = *(E32Image*)aPtr;
   350 	TUint32* destExport=(TUint32*)pI->iExportDirLoad;
   380 
   351 	TInt i=pI->iExportDirCount;
   381 	// Dump everything potentially useful that we know about the exporter ...
   352 	TUint32 codeBase=pI->iCodeRunAddress;
   382 	__LDRTRACE(MyPrintf("RelocateExports: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
   353 	while (i-->0)
   383 						exporter.iUseCodePaging, exporter.iRomImageHeader, exporter.iHeader));
   354 		*destExport+++=codeBase;
   384 	__LDRTRACE(MyPrintf("  iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
       
   385 						exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
       
   386 						exporter.iCodeSize, exporter.iTextSize))
       
   387 	__LDRTRACE(MyPrintf("  iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
       
   388 						exporter.iDataLoadAddress, exporter.iDataRunAddress,
       
   389 						exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
       
   390 	__LDRTRACE(MyPrintf("  iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
       
   391 						exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
       
   392 
       
   393 	// It turns out that very little of the exporter info is useful! For
       
   394 	// example, the required code and data deltas are NOT those provided
       
   395 	// by the exporter, nor are the load addresses relevant ... :(
       
   396 	//
       
   397 	// In the case of a PE-derived image, the entries in the export table
       
   398 	// are expressed in terms of offsets into the image file, rather than
       
   399 	// locations in memory. Each therefore needs to be relocated by the
       
   400 	// difference between its file offset and its run address.
       
   401 	//
       
   402 	// It is assumed that the code segment appears before the data segment
       
   403 	// in the file; therefore, export table entries with values between 0
       
   404 	// and (exporter.iCodeSize) refer to the text segment, while higher
       
   405 	// values represent references to data addresses. Since the run addresses
       
   406 	// of code and data segments may be different, each type of export must
       
   407 	// be relocated with respect to the correct section.
       
   408 	//
       
   409 	// The following express the start and finish of each section in terms of
       
   410 	// file offsets and then derive the required adjustments to the entries
       
   411 	// in the export table ...
       
   412 	TUint32 codeStart = 0;							// compiler whinges if this is 'const' :(
       
   413 	const TUint32 codeFinish = codeStart + exporter.iCodeSize;
       
   414 	const TUint32 dataStart = codeFinish;
       
   415 	const TUint32 dataFinish = dataStart + exporter.iTotalDataSize;
       
   416 	const TUint32 codeDelta = exporter.iCodeRunAddress - codeStart;
       
   417 	const TUint32 dataDelta = exporter.iDataRunAddress - dataStart;
       
   418 
       
   419 	TUint32* destExport = (TUint32*)exporter.iExportDirLoad;
       
   420 	for (TInt i = exporter.iExportDirCount; --i >= 0; )
       
   421 		{
       
   422 		TUint32 relocAddr = *destExport;
       
   423 		TUint32 newValue;
       
   424 		if (relocAddr >= codeStart && relocAddr < codeFinish)
       
   425 			newValue = relocAddr + codeDelta;		// points to text/rdata section
       
   426 		else if (relocAddr >= dataStart && relocAddr < dataFinish)
       
   427 			newValue = relocAddr + dataDelta;		// points to data/bss section
       
   428 		else
       
   429 			newValue = relocAddr;					// unknown - just leave it alone
       
   430 		*destExport++ = newValue;
       
   431 
       
   432 		__LDRTRACE(MyPrintf("RelocateExports: export %d %08x => %08x %c",
       
   433 							exporter.iExportDirCount-i, relocAddr, newValue,
       
   434 							(relocAddr >= codeStart && relocAddr < codeFinish) ? 'C' :
       
   435 							(relocAddr >= dataStart && relocAddr < dataFinish) ? 'D' : 'X'));
       
   436 		}
       
   437 
   355 	return 0;
   438 	return 0;
   356 	}
   439 	}
   357 
   440 
   358 
   441 
   359 struct SFixupImportAddressesInfo
   442 struct SFixupImportAddressesInfo
   360 	{
   443 	{
   361 	TUint32* iIat;
   444 	TUint32* iIat;					// Next part of IAT to be fixed up
   362 	TUint32* iExportDir;
   445 	E32Image* iExporter;			// Module from which we're importing
   363 	TUint32 iExportDirEntryDelta;
   446 	TInt iNumImports;				// Number of imports from this exporter
   364 	TInt iNumImports;
   447 
   365 	E32Image* iExporter;
       
   366 	/**
   448 	/**
   367 	For demand paging, this points to the buffer which is populated
   449 	For demand paging, this points to the buffer which is populated
   368 	so each page can be fixed up as it is loaded in.
   450 	so each page can be fixed up as it is loaded in.
   369 	*/
   451 	*/
   370 	TUint64* iFixup64;
   452 	TUint64* iFixup64;
   376 
   458 
   377 /**
   459 /**
   378 Fix up the import address table, used for 'PE derived' executables.
   460 Fix up the import address table, used for 'PE derived' executables.
   379 @param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
   461 @param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
   380 			SFixupImportAddressesInfo::iIat is updated by this function.
   462 			SFixupImportAddressesInfo::iIat is updated by this function.
       
   463 
       
   464 For a given importer, this function will be called once for each image from which
       
   465 objects are imported, and each time it will update the relevant portion of the
       
   466 importer's IAT, until all imports from all exporters have been processed.
   381 */
   467 */
   382 TInt svFixupImportAddresses(TAny* aPtr)
   468 TInt svFixupImportAddresses(TAny* aPtr)
   383 	{
   469 	{
   384 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
   470 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
   385 
   471 	E32Image& exporter = *info.iExporter;
   386 	TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
   472 
   387 	TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
   473 #ifdef _DEBUG
   388 
   474 	__LDRTRACE(MyPrintf(">svFixupImportAddresses %d imports, code@%08x, fixup@%08x exporter@%08x",
   389 	TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
   475 						info.iNumImports, info.iCodeLoadAddress, info.iFixup64, info.iExporter));
   390 	TUint32 exp_delta = info.iExportDirEntryDelta;
   476 
       
   477 	// Dump everything potentially useful that we know about the exporter ...
       
   478 	__LDRTRACE(MyPrintf("%S: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
       
   479 						&exporter.iFileName, exporter.iUseCodePaging,
       
   480 						exporter.iRomImageHeader, exporter.iHeader));
       
   481 	__LDRTRACE(MyPrintf("iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
       
   482 						exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
       
   483 						exporter.iCodeSize, exporter.iTextSize))
       
   484 	__LDRTRACE(MyPrintf("iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
       
   485 						exporter.iDataLoadAddress, exporter.iDataRunAddress,
       
   486 						exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
       
   487 	__LDRTRACE(MyPrintf("iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
       
   488 						exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
       
   489 
       
   490 	if (exporter.iRomImageHeader)
       
   491 		{
       
   492 		const TRomImageHeader& rh = *exporter.iRomImageHeader;
       
   493 		__LDRTRACE(MyPrintf("ROM: iCodeAddress %08x, iCodeSize %x, iTextSize %x",
       
   494 							rh.iCodeAddress, rh.iCodeSize, rh.iTextSize));
       
   495 		__LDRTRACE(MyPrintf("ROM: iDataAddress %08x, iDataSize %x, iBssSize %x",
       
   496 							rh.iDataAddress, rh.iDataSize, rh.iBssSize));
       
   497 		__LDRTRACE(MyPrintf("ROM: iDataBssLinearBase %08x, iTotalDataSize %x",
       
   498 							rh.iDataBssLinearBase, rh.iTotalDataSize));
       
   499 		}
       
   500 
       
   501 	if (exporter.iHeader)
       
   502 		{
       
   503 		const E32ImageHeader& ih = *exporter.iHeader;
       
   504 		__LDRTRACE(MyPrintf("HEAD: iCodeBase %08x, iCodeSize %x, iTextSize %x",
       
   505 							ih.iCodeBase, ih.iCodeSize, ih.iTextSize));
       
   506 		__LDRTRACE(MyPrintf("HEAD: iDataBase %08x, iDataSize %x, iBssSize %x",
       
   507 							ih.iDataBase, ih.iDataSize, ih.iBssSize));
       
   508 		}
       
   509 #endif // _DEBUG
       
   510 
       
   511 	// 'exportDir' points to the address of the 0th ordinal (symbol name data);
       
   512 	// ordinary exports start from ordinal 1
       
   513 	const TUint32* const exportDir = (TUint32*)exporter.iExportDirLoad - KOrdinalBase;
       
   514 	const TUint32 maxOrdinal = (TUint32)exporter.iExportDirCount;
       
   515 	const TUint32 absentOrdinal = (TUint32)exporter.iFileEntryPoint;
   391 
   516 
   392 	TUint32* iat = info.iIat;
   517 	TUint32* iat = info.iIat;
   393 	TUint32* iatE = iat+info.iNumImports;
   518 	TUint32* const iatEnd = iat + info.iNumImports;
   394 	for(; iat<iatE; ++iat)
   519 	for (; iat < iatEnd; ++iat)
   395 		{
   520 		{
   396 		TUint32 imp = *iat;
   521 		// Each IAT slot contains the ordinal number of the export to be imported from
   397 		if(imp>maxOrdinal)
   522 		// the exporter. We use that index to locate the address of the export itself.
       
   523 		TUint32 ordinal = *iat;
       
   524 		if (ordinal > maxOrdinal)
   398 			return KErrNotSupported;
   525 			return KErrNotSupported;
   399 
   526 
   400 		TUint32 writeValue;
   527 		// If the import number is 0 (symbol name data), and the exporter doesn't provide
   401 		if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
   528 		// this, we don't regard it as an error; we just skip this block, leaving the
   402 			{
   529 		// address set to 0. For all other valid cases, we index the export directory to
   403 			// attempt to import ordinal zero (symbol name data) from an executable
   530 		// find the exported object's address (which has already been relocated) ...
   404 			// which doesn't export this information, use NULL for imported value in this case...
   531 		TUint32 newValue = 0;
   405 			writeValue = NULL;
   532 		if (ordinal > 0 || (exporter.iAttr & ECodeSegAttNmdExpData))
   406 			}
   533 			{
       
   534 			TUint32 expAddr = exportDir[ordinal];
       
   535 			if (expAddr == 0 || expAddr == absentOrdinal)
       
   536 				return KErrNotSupported;
       
   537 			// The new value is just the address of the export, no adjustment needed
       
   538 			newValue = expAddr;
       
   539 			}
       
   540 
       
   541 		__LDRTRACE(MyPrintf("svFixupImportAddresses: import[%d]@%08x is export[%d] == %08x",
       
   542 							iat - info.iIat, iat, ordinal, newValue));
       
   543 
       
   544 		// In non-paged code, we can simply replace the ordinals in the IAT with the
       
   545 		// object addresses to which they refer once and for all. However, in a code
       
   546 		// paging system, the IAT may be thrown away and later reloaded from the code
       
   547 		// image; therefore, we need to save the updates in the buffer pointed to by
       
   548 		// 'iFixup64' so that they can be reapplied each time the code page(s)
       
   549 		// containing (parts of the) IAT are reloaded. The fixup entries are in the
       
   550 		// form of 64-bit words, with the 32-bit address-to-be-fixed-up in the upper
       
   551 		// half and the value-to-be-stored-there in the lower half -- the multiple
       
   552 		// casts are needed to stop some compilers whinging about converting a
       
   553 		// pointer to a 64-bit integral type :(
       
   554 		if (!info.iFixup64)
       
   555 			*iat = newValue;
   407 		else
   556 		else
   408 			{
   557 			*info.iFixup64++ = ((TUint64)(TUintPtr)iat << 32) | newValue;
   409 			// get imported value from exporter...
   558 		}
   410 			TUint32 exp_addr = exp_dir[imp];
   559 
   411 			if(exp_addr==0 || exp_addr==absentOrdinal)
   560 	// Finally, update 'info.iIat' to show which imports have been processed
   412 				return KErrNotSupported;
       
   413 			writeValue = exp_addr + exp_delta;
       
   414 			}
       
   415 
       
   416 		// if not code paging then directly fix up the import...
       
   417 		if (info.iFixup64 == 0)
       
   418 			*iat = writeValue;
       
   419 		else
       
   420 		// ...otherwise defer until the page is fixed up
       
   421 			{
       
   422 			TUint64 iat64 = reinterpret_cast<TUint64>(iat);
       
   423 			*info.iFixup64++ = (iat64 << 32) | writeValue;
       
   424 			}
       
   425 		}
       
   426 
       
   427 	info.iIat = iat;
   561 	info.iIat = iat;
   428 	return KErrNone;
   562 	return KErrNone;
   429 	}
   563 	}
   430 
   564 
   431 
   565 
   434 @param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
   568 @param aPtr Pointer to function arguments (SFixupImportAddressesInfo structure).
   435 */
   569 */
   436 TInt svElfDerivedFixupImportAddresses(TAny* aPtr)
   570 TInt svElfDerivedFixupImportAddresses(TAny* aPtr)
   437 	{
   571 	{
   438 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
   572 	SFixupImportAddressesInfo& info = *(SFixupImportAddressesInfo*)aPtr;
   439 	TUint32 maxOrdinal = (TUint32)info.iExporter->iExportDirCount;
   573 	E32Image& exporter = *info.iExporter;
   440 	TUint32 absentOrdinal = (TUint32)info.iExporter->iFileEntryPoint;
   574 
   441 
   575 #ifdef _DEBUG
   442 	TUint32* exp_dir = info.iExportDir - KOrdinalBase; // address of 0th ordinal
   576 	__LDRTRACE(MyPrintf(">svElfDerivedFixupImportAddresses %d imports, code@%08x, fixup@%08x exporter@%08x",
   443 	TUint32 exp_delta = info.iExportDirEntryDelta;
   577 						info.iNumImports, info.iCodeLoadAddress, info.iFixup64, info.iExporter));
   444 	TUint32 code = info.iCodeLoadAddress;
   578 
       
   579 	// Dump everything potentially useful that we know about the exporter ...
       
   580 	__LDRTRACE(MyPrintf("%S: paged? %d, iRomImageHeader@%08x, iHeader@%08x",
       
   581 						&exporter.iFileName, exporter.iUseCodePaging,
       
   582 						exporter.iRomImageHeader, exporter.iHeader));
       
   583 	__LDRTRACE(MyPrintf("iCodeLoadAddress %08x, iCodeRunAddress %08x, iCodeSize %x iTextSize %x",
       
   584 						exporter.iCodeLoadAddress, exporter.iCodeRunAddress,
       
   585 						exporter.iCodeSize, exporter.iTextSize))
       
   586 	__LDRTRACE(MyPrintf("iDataLoadAddress %08x, iDataRunAddress %08x, iDataSize %x iBssSize %x iTotalDataSize %x",
       
   587 						exporter.iDataLoadAddress, exporter.iDataRunAddress,
       
   588 						exporter.iDataSize, exporter.iBssSize, exporter.iTotalDataSize));
       
   589 	__LDRTRACE(MyPrintf("iCodeDelta, %x iDataDelta %x, iExportDirEntryDelta %x",
       
   590 						exporter.iCodeDelta, exporter.iDataDelta, exporter.iExportDirEntryDelta));
       
   591 
       
   592 	if (exporter.iRomImageHeader)
       
   593 		{
       
   594 		const TRomImageHeader& rh = *exporter.iRomImageHeader;
       
   595 		__LDRTRACE(MyPrintf("ROM: iCodeAddress %08x, iCodeSize %x, iTextSize %x",
       
   596 							rh.iCodeAddress, rh.iCodeSize, rh.iTextSize));
       
   597 		__LDRTRACE(MyPrintf("ROM: iDataAddress %08x, iDataSize %x, iBssSize %x",
       
   598 							rh.iDataAddress, rh.iDataSize, rh.iBssSize));
       
   599 		__LDRTRACE(MyPrintf("ROM: iDataBssLinearBase %08x, iTotalDataSize %x",
       
   600 							rh.iDataBssLinearBase, rh.iTotalDataSize));
       
   601 		}
       
   602 
       
   603 	if (exporter.iHeader)
       
   604 		{
       
   605 		const E32ImageHeader& ih = *exporter.iHeader;
       
   606 		__LDRTRACE(MyPrintf("HEAD: iCodeBase %08x, iCodeSize %x, iTextSize %x",
       
   607 							ih.iCodeBase, ih.iCodeSize, ih.iTextSize));
       
   608 		__LDRTRACE(MyPrintf("HEAD: iDataBase %08x, iDataSize %x, iBssSize %x",
       
   609 							ih.iDataBase, ih.iDataSize, ih.iBssSize));
       
   610 		}
       
   611 #endif // _DEBUG
       
   612 
       
   613 	// Here we calculate the bounds of each section of the exporter, as
       
   614 	// code and data exports may have to be offset by different amounts.
       
   615 	// Unfortunately, the required information seems to be in several
       
   616 	// different places, depending on whether the code is ROM or RAM, etc
       
   617 	TUint32 codeStart = exporter.iCodeRunAddress;
       
   618 	TUint32 codeEnd = codeStart + exporter.iCodeSize;
       
   619 	TUint32 dataStart = exporter.iDataRunAddress;
       
   620 	TUint32 dataEnd = dataStart + exporter.iTotalDataSize;
       
   621 
       
   622 	if (exporter.iRomImageHeader)
       
   623 		{
       
   624 		const TRomImageHeader& rh = *exporter.iRomImageHeader;
       
   625 		codeStart = rh.iCodeAddress;
       
   626 		codeEnd = codeStart + rh.iCodeSize;
       
   627 		dataStart = rh.iDataBssLinearBase;
       
   628 		dataEnd = dataStart + rh.iTotalDataSize;
       
   629 		}
       
   630 
       
   631 	if (exporter.iHeader)
       
   632 		{
       
   633 		const E32ImageHeader& ih = *exporter.iHeader;
       
   634 		codeStart = ih.iCodeBase;
       
   635 		codeEnd = codeStart + ih.iCodeSize;
       
   636 		dataStart = ih.iDataBase;
       
   637 		dataEnd = dataStart + ih.iDataSize + ih.iBssSize;
       
   638 		}
       
   639 
       
   640 	// 'exportDir' points to the address of the 0th ordinal (symbol name data);
       
   641 	// ordinary exports start from ordinal 1
       
   642 	const TUint32* const exportDir = (TUint32*)exporter.iExportDirLoad - KOrdinalBase;
       
   643 	const TUint32 maxOrdinal = (TUint32)exporter.iExportDirCount;
       
   644 	const TUint32 absentOrdinal = (TUint32)exporter.iFileEntryPoint;
       
   645 
       
   646 	const TUint32 codeDelta = exporter.iCodeDelta;
       
   647 	const TUint32 dataDelta = exporter.iDataDelta;
       
   648 	const TUint32 dirDelta = exporter.iExportDirEntryDelta;
       
   649 	TUint8* const codeBase = (TUint8*)info.iCodeLoadAddress;
   445 
   650 
   446 	TUint32* iol = info.iImportOffsetList;
   651 	TUint32* iol = info.iImportOffsetList;
   447 	TUint32* iolE = iol+info.iNumImports;
   652 	TUint32* const iolEnd = iol + info.iNumImports;
   448 	for(; iol<iolE; ++iol)
   653 	for(; iol < iolEnd; ++iol)
   449 		{
   654 		{
   450 		TUint32* impPtr = (TUint32*)(code+*iol);
   655 		// Whereas the PE format's IAT contains ordinals to be imported, the ELF IOL
   451 		TUint32 impd = *impPtr;
   656 		// (Import Offset List) is a list of offsets (within the importer's code) of
   452 		TUint32 imp = impd & 0xffff;
   657 		// the locations that contain references to imported objects.
   453 		TUint32 offset = impd >> 16;
   658 		//
   454 		if(imp>maxOrdinal)
   659 		// At the start of this process, each such location contains a composite value,
       
   660 		// of which the low 16 bits indicate the ordinal to be imported from the
       
   661 		// exporter's directory, and the upper 16 provide an optional adjustment to
       
   662 		// be added to the imported value.
       
   663 		//
       
   664 		// This composite value has to be replaced by the actual address of the
       
   665 		// object being imported (plus the adjustment factor, if any).
       
   666 		TUint32 codeOffset = *iol;
       
   667 		TUint32* codePtr = (TUint32*)(codeBase+codeOffset);
       
   668 		TUint32 importInfo = *codePtr;
       
   669 		TUint32 ordinal = importInfo & 0xffff;
       
   670 		TUint32 adjustment = importInfo >> 16;
       
   671 		if(ordinal > maxOrdinal)
   455 			return KErrNotSupported;
   672 			return KErrNotSupported;
   456 
   673 
   457 		TUint32 writeValue;
   674 		// If the import number is 0 (symbol name data), and the exporter doesn't provide
   458 		if(imp==0 && !(info.iExporter->iAttr&ECodeSegAttNmdExpData))
   675 		// this, we don't regard it as an error; we just skip this block, leaving the
   459 			{
   676 		// address set to 0. For all other valid cases, we index the export directory to find
   460 			// attempt to import ordinal zero (symbol name data) from an executable
   677 		// the exported object's address (which may OR MAY NOT have already been relocated)
   461 			// which doesn't export this information, use NULL for imported value in this case...
   678 		TUint32 expAddr = 0;
   462 			writeValue = NULL;
   679 		TUint32 newValue = 0;
   463 			}
   680 		if (ordinal > 0 || (exporter.iAttr & ECodeSegAttNmdExpData))
       
   681 			{
       
   682 			expAddr = exportDir[ordinal];
       
   683 			if(expAddr == 0 || expAddr == absentOrdinal)
       
   684 				return KErrNotSupported;
       
   685 
       
   686 			// If the exporter does not use code paging, then the entries in the export
       
   687 			// table will already have been relocated along with its text section. In
       
   688 			// the paged case, however, the relocation will have been deferred until the
       
   689 			// relevant pages are (re)loaded; therefore, we have to deduce here whether
       
   690 			// each export is code or data so that we can apply the correct delta ...
       
   691 			TUint32 sectionDelta;
       
   692 			if (!exporter.iUseCodePaging)
       
   693 				sectionDelta = dirDelta;
       
   694 			else if (expAddr >= codeStart && expAddr < codeEnd)
       
   695 				sectionDelta = codeDelta;			// points to text/rdata section
       
   696 			else if (expAddr >= dataStart && expAddr < dataEnd)
       
   697 				sectionDelta = dataDelta;			// points to data/bss section
       
   698 			else
       
   699 				sectionDelta = dirDelta;			// unknown - assume nonpaged?
       
   700 			newValue = expAddr + sectionDelta + adjustment;
       
   701 			}
       
   702 
       
   703 		__LDRTRACE(MyPrintf("svElfDerivedFixupImportAddresses: import[%d] (%08x:%08x) is export[%d] %08x+%08x => %08x",
       
   704 							iol - info.iImportOffsetList, codePtr, importInfo, ordinal, expAddr, adjustment, newValue));
       
   705 
       
   706 		// In non-paged code, we can simply replace the ordinals in the IAT with the
       
   707 		// object addresses to which they refer once and for all. However, in a code
       
   708 		// paging system, the IAT may be thrown away and later reloaded from the code
       
   709 		// image; therefore, we need to save the updates in the buffer pointed to by
       
   710 		// 'iFixup64' so that they can be reapplied each time the code page(s)
       
   711 		// containing (parts of the) IAT are reloaded. The fixup entries are in the
       
   712 		// form of 64-bit words, with the 32-bit address-to-be-fixed-up in the upper
       
   713 		// half and the value-to-be-stored-there in the lower half -- the multiple
       
   714 		// casts are needed to stop some compilers whinging about converting a
       
   715 		// pointer to a 64-bit integral type :(
       
   716 		if (!info.iFixup64)
       
   717 			*codePtr = newValue;
   464 		else
   718 		else
   465 			{
   719 			*info.iFixup64++ = ((TUint64)(TUintPtr)codePtr << 32) | newValue;
   466 			// get imported value from exporter...
   720 		}
   467 			TUint32 exp_addr = exp_dir[imp];
   721 
   468 			if(exp_addr==0 || exp_addr==absentOrdinal)
       
   469 				return KErrNotSupported;
       
   470 			writeValue = exp_addr + exp_delta + offset;
       
   471 			}
       
   472 
       
   473 		// if not code paging then directly fix up the import...
       
   474 		if (info.iFixup64 == 0)
       
   475 			*impPtr = writeValue;
       
   476 		// ...otherwise defer until the page is fixed up
       
   477 		else
       
   478 			{
       
   479 			TUint64 impPtr64 = reinterpret_cast<TUint64>(impPtr);
       
   480 			*info.iFixup64++ = (impPtr64 << 32) | writeValue;
       
   481 			}
       
   482 		}
       
   483 	return KErrNone;
   722 	return KErrNone;
   484 	}
   723 	}
   485 
   724 
   486 
   725 
   487 /**
   726 /**
  2832 			//	imports anything
  3071 			//	imports anything
  2833 			//	This recursive horror *will* terminate because it is only called
  3072 			//	This recursive horror *will* terminate because it is only called
  2834 			//	on "new" dlls
  3073 			//	on "new" dlls
  2835 			if (e->iDepCount && !e->iAlreadyLoaded && e->iIsDll)
  3074 			if (e->iDepCount && !e->iAlreadyLoaded && e->iIsDll)
  2836 				{
  3075 				{
  2837 				__IF_DEBUG(Printf("****Go recursive****"));
  3076 				__IF_DEBUG(Printf("****Going recursive****"));
  2838 				r = e->LoadDlls(aArray);
  3077 				r = e->LoadDlls(aArray);
       
  3078 				__IF_DEBUG(Printf("****Returned from recursion****"));
  2839 				if (r!=KErrNone)
  3079 				if (r!=KErrNone)
  2840 					{
  3080 					{
  2841 					return r;
  3081 					return r;
  2842 					}
  3082 					}
  2843 				}
  3083 				}
  2954 
  3194 
  2955 			//	Get the exporter's export directory
  3195 			//	Get the exporter's export directory
  2956 			r = exp->ReadExportDirLoad();
  3196 			r = exp->ReadExportDirLoad();
  2957 			if (r != KErrNone)
  3197 			if (r != KErrNone)
  2958 				return r;
  3198 				return r;
  2959 			info.iExportDir = (TUint32*)exp->iExportDirLoad;
       
  2960 			info.iExportDirEntryDelta = exp->iExportDirEntryDelta;
       
  2961 			info.iNumImports = block->iNumberOfImports;
  3199 			info.iNumImports = block->iNumberOfImports;
  2962 			info.iExporter = exp;
  3200 			info.iExporter = exp;
  2963 
  3201 
  2964 			// if demand paging, expand the import fixup buffer for this next exporting DLL
  3202 			// if demand paging, expand the import fixup buffer for this next exporting DLL
  2965 			if (! imp->iUseCodePaging)
  3203 			if (! imp->iUseCodePaging)
  2974 			// call function in supervisor mode to fix up the import addresses.
  3212 			// call function in supervisor mode to fix up the import addresses.
  2975 			impfmt = imp->iHeader->ImportFormat();
  3213 			impfmt = imp->iHeader->ImportFormat();
  2976 			if (impfmt == KImageImpFmt_ELF)
  3214 			if (impfmt == KImageImpFmt_ELF)
  2977 				{
  3215 				{
  2978 				info.iImportOffsetList = (TUint32*)(block+1);
  3216 				info.iImportOffsetList = (TUint32*)(block+1);
       
  3217 				__IF_DEBUG(Printf("Import format ELF (%08x); info@%08x", impfmt, &info));
  2979 				r = ExecuteInSupervisorMode(&svElfDerivedFixupImportAddresses, &info);
  3218 				r = ExecuteInSupervisorMode(&svElfDerivedFixupImportAddresses, &info);
  2980 				}
  3219 				}
  2981 			else
  3220 			else
       
  3221 				{
       
  3222 				__IF_DEBUG(Printf("Import format PE (%08x); info@%08x", impfmt, &info));
  2982 				r = ExecuteInSupervisorMode(&svFixupImportAddresses, &info);
  3223 				r = ExecuteInSupervisorMode(&svFixupImportAddresses, &info);
       
  3224 				}
  2983 
  3225 
  2984 			if (r != KErrNone)
  3226 			if (r != KErrNone)
  2985 				{
  3227 				{
  2986 				__IF_DEBUG(Printf("svFixupImportAddresses returns %d", r));
  3228 				__IF_DEBUG(Printf("svFixupImportAddresses returns %d", r));
  2987 				return r;
  3229 				return r;
  3056 
  3298 
  3057 @return					Symbian OS error code.
  3299 @return					Symbian OS error code.
  3058 */
  3300 */
  3059 TInt E32Image::BuildImportFixupTable()
  3301 TInt E32Image::BuildImportFixupTable()
  3060 	{
  3302 	{
  3061 	__IF_DEBUG(Printf(">BuildImportFixupTable,0x%08x,%d", iFixups, iFixupCount));
  3303 	__IF_DEBUG(Printf(">BuildImportFixupTable,%d@%08x,%08x", iFixupCount, iFixups, iCodeLoadAddress));
       
  3304 
       
  3305 #ifdef _DEBUG
       
  3306 	// Dump the incoming fixup table if loader tracing enabled. Each item is an
       
  3307 	// (address, value) pair, where the address and the value are 32 bits each.
       
  3308 	TInt i;
       
  3309 	for (i = 0; i < iFixupCount; ++i)
       
  3310 		{
       
  3311 		TUint64 x = iFixups[i];
       
  3312 		__IF_DEBUG(Printf("%04x: %08x %08x", i*sizeof(TUint64), I64HIGH(x), I64LOW(x)));
       
  3313 		}
       
  3314 #endif	// DEBUG
  3062 
  3315 
  3063 	// sort the array in address order, to organize by page
  3316 	// sort the array in address order, to organize by page
  3064 	RArray<TUint64> fixup64ToSort(sizeof(TUint64), iFixups, iFixupCount);
  3317 	RArray<TUint64> fixup64ToSort(sizeof(TUint64), iFixups, iFixupCount);
  3065 	// SortUnsigned doesn't work on TUint64
  3318 	// SortUnsigned doesn't work on TUint64
  3066 	fixup64ToSort.Sort(TLinearOrder<TUint64>(Uint64LinearOrderFunc));
  3319 	fixup64ToSort.Sort(TLinearOrder<TUint64>(Uint64LinearOrderFunc));
  3068 	// now have <address | new-value> pairs, organize into pages.
  3321 	// now have <address | new-value> pairs, organize into pages.
  3069 	// Each page is stored as fXXX YYYY ZZZZ where YYYY ZZZZ is written
  3322 	// Each page is stored as fXXX YYYY ZZZZ where YYYY ZZZZ is written
  3070 	// to the word at offset XXX.  (See PREQ1110 Design Sketch v1.0 S3.1.1.2.3.2.)
  3323 	// to the word at offset XXX.  (See PREQ1110 Design Sketch v1.0 S3.1.1.2.3.2.)
  3071 
  3324 
  3072 	TUint32 pageCount = SizeToPageCount(iCodeSize);
  3325 	TUint32 pageCount = SizeToPageCount(iCodeSize);
  3073 	iImportFixupTableSize = (pageCount+1) * sizeof(TUint32) + iFixupCount * 3 * sizeof(TUint16);
  3326 	iImportFixupTableSize = (pageCount+1)*sizeof(TUint32) + 3*iFixupCount*sizeof(TUint16);
  3074 	iImportFixupTable = (TUint32*) User::Alloc(iImportFixupTableSize);
  3327 	iImportFixupTable = (TUint32*) User::Alloc(iImportFixupTableSize);
  3075 	__IF_DEBUG(Printf("iImportFixupTable=0x%08x", iImportFixupTable));
  3328 	__IF_DEBUG(Printf("iImportFixupTable=0x%08x", iImportFixupTable));
  3076 	if (iImportFixupTable == 0)
  3329 	if (iImportFixupTable == 0)
  3077 		return KErrNoMemory;
  3330 		return KErrNoMemory;
  3078 
  3331 
  3119 
  3372 
  3120 	// sentinel value marks end of table
  3373 	// sentinel value marks end of table
  3121 	while (++lastPage <= pageCount)
  3374 	while (++lastPage <= pageCount)
  3122 		iImportFixupTable[lastPage] = iImportFixupTableSize;
  3375 		iImportFixupTable[lastPage] = iImportFixupTableSize;
  3123 
  3376 
  3124 	__IF_DEBUG(Printf("processed table (size=%d,pageCount=%d)", iImportFixupTableSize, pageCount));
       
  3125 
       
  3126 #ifdef _DEBUG
  3377 #ifdef _DEBUG
  3127 	// dump the import fixup table if loader tracing enabled
  3378 	__IF_DEBUG(Printf("processed fixup table (size=%d,pageCount=%d)", iImportFixupTableSize, pageCount));
       
  3379 
       
  3380 	// Dump the processed fixup table if loader tracing enabled. The dump is in two
       
  3381 	// parts; first, the page indexes (1 word per page), then the entries describing
       
  3382 	// the items to be relocated, each of which is a 16-bit offset-within-page and a
       
  3383 	// 32-bit value to be stored there.
       
  3384 	for (i = 0; i <= (TInt)pageCount; ++i)
       
  3385 		__IF_DEBUG(Printf("%04x: %08x", i*4, iImportFixupTable[i]));
       
  3386 
  3128 	const TUint16* table16 = (const TUint16*)iImportFixupTable;
  3387 	const TUint16* table16 = (const TUint16*)iImportFixupTable;
  3129 	const TInt halfWordsInTable = iImportFixupTableSize / 2;
  3388 	const TInt halfWordsInTable = iImportFixupTableSize / 2;
  3130 	for (TInt i = 0; i < halfWordsInTable; i += 4)
  3389 	for (i *= 2; i < halfWordsInTable; i += 3)
  3131 		{
  3390 		__IF_DEBUG(Printf("%04x: %04x %04x%04x", i*2, table16[i+0], table16[i+2], table16[i+1]));
  3132 		__IF_DEBUG(Printf(
       
  3133 			"%04x: %04x %04x %04x %04x",
       
  3134 			i * 2, table16[i+0], table16[i+1], table16[i+2], table16[i+3]));
       
  3135 		}
       
  3136 #endif
  3391 #endif
  3137 
  3392 
  3138 	User::Free(iFixups);
  3393 	User::Free(iFixups);
  3139 	iFixups = 0;
  3394 	iFixups = 0;
  3140 	return KErrNone;
  3395 	return KErrNone;