742 } |
742 } |
743 |
743 |
744 |
744 |
745 |
745 |
746 |
746 |
|
747 TBool TEntryPointList::AlreadyCalled(TLinAddr aEP) |
|
748 { |
|
749 TInt i; |
|
750 |
|
751 // if we find it in the list before the current one |
|
752 // then it was already called, return true |
|
753 for (i=0; i<iCurrentEP; ++i) |
|
754 if (iEPs[i] == aEP) |
|
755 return ETrue; |
|
756 |
|
757 // if it *is* the current one (i==iCurrentEP here) |
|
758 // then we're in some kind of hideous cycle. There is no |
|
759 // way to resolve this that isn't wrong, but some people |
|
760 // may depend on it anyway. The safest thing to do is to |
|
761 // just claim the EP is already called and hope that |
|
762 // the constructors aren't actually dependent on each other. |
|
763 if (iEPs[i] == aEP) |
|
764 return ETrue; |
|
765 |
|
766 // if we find it *after* the current one then it's not |
|
767 // already been called, but we need to call it now |
|
768 // rather than when we get that far back up the stack, |
|
769 // so set that copy to -1. |
|
770 for (++i; i<iNumEPs; ++i) |
|
771 if (iEPs[i] == aEP) |
|
772 iEPs[i] = 0xFFFFFFFFU; |
|
773 |
|
774 // if this is not the top of the stack recurse, otherwise |
|
775 // return false so the current load will call it |
|
776 if (iPrevList) |
|
777 return iPrevList->AlreadyCalled(aEP); |
|
778 else |
|
779 return EFalse; |
|
780 } |
|
781 |
|
782 |
|
783 TInt TEntryPointList::CallEPs() |
|
784 { |
|
785 // The TLS entry for KNestedEntryPointCallKey is the head |
|
786 // of a linked list of TEntryPointList objects. Add this one |
|
787 // to the front of the list. iPrevList will end up NULL if |
|
788 // there is no nested load yet. |
|
789 // Only one thread per process can be doing a load at a time |
|
790 // because of the DLL lock, so using TLS for this is fine. |
|
791 iPrevList=(TEntryPointList*)UserSvr::DllTls(KNestedEntryPointCallKey, KDllUid_Special); |
|
792 TInt r=UserSvr::DllSetTls(KNestedEntryPointCallKey, KDllUid_Special, this); |
|
793 if (r != KErrNone) |
|
794 return r; |
|
795 |
|
796 // call each entry point unless it's already been called higher |
|
797 // in the nested loading process, or it's been set to -1 because |
|
798 // it was called lower in the nested load. |
|
799 for (iCurrentEP=0; iCurrentEP<iNumEPs; ++iCurrentEP) |
|
800 { |
|
801 TLinAddr ep=iEPs[iCurrentEP]; |
|
802 if (ep != 0xFFFFFFFFU && (!iPrevList || !iPrevList->AlreadyCalled(ep))) |
|
803 { |
|
804 TLibraryEntry f=(TLibraryEntry)ep; |
|
805 r = (*f)(KModuleEntryReasonProcessAttach); |
|
806 if (r != KErrNone) |
|
807 break; |
|
808 } |
|
809 } |
|
810 |
|
811 // Take this object off the list before returning |
|
812 UserSvr::DllSetTls(KNestedEntryPointCallKey, KDllUid_Special, iPrevList); |
|
813 |
|
814 return r; |
|
815 } |
|
816 |
|
817 |
|
818 |
|
819 |
747 void CallStaticEntryPoints(TBool aInit) |
820 void CallStaticEntryPoints(TBool aInit) |
748 { |
821 { |
749 TLinAddr ep[KMaxLibraryEntryPoints]; |
822 TEntryPointList eplist; |
750 TInt numEps=KMaxLibraryEntryPoints; |
823 eplist.iNumEPs=KMaxLibraryEntryPoints; |
751 TInt r=E32Loader::StaticCallList(numEps, ep); |
824 TInt r=E32Loader::StaticCallList(eplist.iNumEPs, eplist.iEPs); |
752 if (r!=KErrNone) |
825 if (r!=KErrNone) |
753 return; |
826 return; |
|
827 eplist.iNumEPs -= 1; // last EP is always process entry point |
754 if (aInit) |
828 if (aInit) |
755 { |
829 { |
756 for (TInt i=0; i<numEps-1; ++i) // last EP is always process entry point |
830 eplist.CallEPs(); |
757 { |
|
758 TLibraryEntry f=(TLibraryEntry)ep[i]; |
|
759 (*f)(KModuleEntryReasonProcessAttach); |
|
760 } |
|
761 } |
831 } |
762 else |
832 else |
763 { |
833 { |
764 for (TInt i=numEps-2; i>=0; --i) // last EP is always process entry point |
834 for (TInt i=eplist.iNumEPs-1; i>=0; --i) |
765 { |
835 { |
766 TLibraryEntry f=(TLibraryEntry)ep[i]; |
836 TLibraryEntry f=(TLibraryEntry)eplist.iEPs[i]; |
767 (*f)(KModuleEntryReasonProcessDetach); |
837 (*f)(KModuleEntryReasonProcessDetach); |
768 } |
838 } |
769 } |
839 } |
770 } |
840 } |
771 |
841 |
2015 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, |
2086 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, |
2016 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, |
2087 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, |
2017 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d |
2088 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d |
2018 }; |
2089 }; |
2019 |
2090 |
2020 /* RVCT 3.1 and 4.0 read past the end of arrays when unrolling loops. |
|
2021 * This only happens when using -O3 -Otime, so force to -O2. |
|
2022 */ |
|
2023 #if __ARMCC_VERSION >= 310000 |
|
2024 #pragma push |
|
2025 #pragma O2 |
|
2026 #endif |
|
2027 |
2091 |
2028 /** |
2092 /** |
2029 Performs a CCITT CRC-32 checksum on the specified data. |
2093 Performs a CCITT CRC-32 checksum on the specified data. |
2030 |
2094 |
2031 On return from this function, the referenced 32 bit integer contains the CRC |
2095 On return from this function, the referenced 32 bit integer contains the CRC |