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 /** |